From ae481feb8e69b0dcd2d6d4b63cfcd3a4df7b8d24 Mon Sep 17 00:00:00 2001 From: cxl Date: Sat, 21 Oct 2017 11:28:01 +0000 Subject: [PATCH] plugin/jpg: updated to version 9b git-svn-id: svn://ultimatepp.org/upp/trunk@11394 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/ODBC/ODBC.cpp | 7 +- uppsrc/ODBC/ODBC.h | 2 + uppsrc/Sql/Sqls.h | 17 +- uppsrc/Sql/src.tpp/Sql$en-us.tpp | 4 +- uppsrc/plugin/jpg/jpg.upp | 50 +- uppsrc/plugin/jpg/lib/README | 366 +-- uppsrc/plugin/jpg/lib/ansi2knr.c | 693 ---- uppsrc/plugin/jpg/lib/cderror.h | 2 + uppsrc/plugin/jpg/lib/cdjpeg.h | 5 +- uppsrc/plugin/jpg/lib/cjpeg.c | 111 +- uppsrc/plugin/jpg/lib/ckconfig.c | 2 +- uppsrc/plugin/jpg/lib/djpeg.c | 12 +- uppsrc/plugin/jpg/lib/example.c | 16 +- uppsrc/plugin/jpg/lib/jaricom.c | 153 + uppsrc/plugin/jpg/lib/jcapimin.c | 14 +- uppsrc/plugin/jpg/lib/jcapistd.c | 5 +- uppsrc/plugin/jpg/lib/jcarith.c | 944 ++++++ uppsrc/plugin/jpg/lib/jccoefct.c | 106 +- uppsrc/plugin/jpg/lib/jccolor.c | 249 +- uppsrc/plugin/jpg/lib/jcdctmgr.c | 565 ++-- uppsrc/plugin/jpg/lib/jcdiffct.c | 409 --- uppsrc/plugin/jpg/lib/jchuff.c | 1338 +++++++- uppsrc/plugin/jpg/lib/jchuff.h | 54 - uppsrc/plugin/jpg/lib/jcinit.c | 33 +- uppsrc/plugin/jpg/lib/jclhuff.c | 599 ---- uppsrc/plugin/jpg/lib/jclossls.c | 78 - uppsrc/plugin/jpg/lib/jclossy.c | 76 - uppsrc/plugin/jpg/lib/jcmainct.c | 125 +- uppsrc/plugin/jpg/lib/jcmarker.c | 228 +- uppsrc/plugin/jpg/lib/jcmaster.c | 531 ++- uppsrc/plugin/jpg/lib/jcodec.c | 53 - uppsrc/plugin/jpg/lib/jconfig.h | 32 +- uppsrc/plugin/jpg/lib/jcparam.c | 340 +- uppsrc/plugin/jpg/lib/jcphuff.c | 848 ----- uppsrc/plugin/jpg/lib/jcpred.c | 298 -- uppsrc/plugin/jpg/lib/jcprepct.c | 16 +- uppsrc/plugin/jpg/lib/jcsample.c | 96 +- uppsrc/plugin/jpg/lib/jcscale.c | 62 - uppsrc/plugin/jpg/lib/jcshuff.c | 661 ---- uppsrc/plugin/jpg/lib/jctrans.c | 115 +- uppsrc/plugin/jpg/lib/jdapimin.c | 60 +- uppsrc/plugin/jpg/lib/jdapistd.c | 7 +- uppsrc/plugin/jpg/lib/jdarith.c | 796 +++++ uppsrc/plugin/jpg/lib/jdatadst.c | 125 +- uppsrc/plugin/jpg/lib/jdatasrc.c | 81 +- uppsrc/plugin/jpg/lib/jdcoefct.c | 122 +- uppsrc/plugin/jpg/lib/jdcolor.c | 423 ++- uppsrc/plugin/jpg/lib/jdct.h | 273 +- uppsrc/plugin/jpg/lib/jddctmgr.c | 160 +- uppsrc/plugin/jpg/lib/jddiffct.c | 398 --- uppsrc/plugin/jpg/lib/jdhuff.c | 1287 +++++++- uppsrc/plugin/jpg/lib/jdhuff.h | 229 -- uppsrc/plugin/jpg/lib/jdinput.c | 519 ++- uppsrc/plugin/jpg/lib/jdlhuff.c | 290 -- uppsrc/plugin/jpg/lib/jdlossls.c | 94 - uppsrc/plugin/jpg/lib/jdlossy.c | 224 -- uppsrc/plugin/jpg/lib/jdmainct.c | 195 +- uppsrc/plugin/jpg/lib/jdmarker.c | 245 +- uppsrc/plugin/jpg/lib/jdmaster.c | 171 +- uppsrc/plugin/jpg/lib/jdmerge.c | 121 +- uppsrc/plugin/jpg/lib/jdphuff.c | 675 ---- uppsrc/plugin/jpg/lib/jdpred.c | 247 -- uppsrc/plugin/jpg/lib/jdsample.c | 176 +- uppsrc/plugin/jpg/lib/jdscale.c | 117 - uppsrc/plugin/jpg/lib/jdshuff.c | 393 --- uppsrc/plugin/jpg/lib/jdtrans.c | 30 +- uppsrc/plugin/jpg/lib/jerror.c | 11 +- uppsrc/plugin/jpg/lib/jerror.h | 38 +- uppsrc/plugin/jpg/lib/jfdctflt.c | 30 +- uppsrc/plugin/jpg/lib/jfdctfst.c | 30 +- uppsrc/plugin/jpg/lib/jfdctint.c | 4332 ++++++++++++++++++++++++- uppsrc/plugin/jpg/lib/jidctflt.c | 62 +- uppsrc/plugin/jpg/lib/jidctfst.c | 105 +- uppsrc/plugin/jpg/lib/jidctint.c | 5046 ++++++++++++++++++++++++++++- uppsrc/plugin/jpg/lib/jidctred.c | 398 --- uppsrc/plugin/jpg/lib/jlossls.h | 149 - uppsrc/plugin/jpg/lib/jlossy.h | 120 - uppsrc/plugin/jpg/lib/jmemdos.c | 8 +- uppsrc/plugin/jpg/lib/jmemmgr.c | 79 +- uppsrc/plugin/jpg/lib/jmorecfg.h | 169 +- uppsrc/plugin/jpg/lib/jpegint.h | 131 +- uppsrc/plugin/jpg/lib/jpeglib.h | 277 +- uppsrc/plugin/jpg/lib/jpegtran.c | 145 +- uppsrc/plugin/jpg/lib/jquant1.c | 13 +- uppsrc/plugin/jpg/lib/jquant2.c | 33 +- uppsrc/plugin/jpg/lib/jutils.c | 90 +- uppsrc/plugin/jpg/lib/jversion.h | 6 +- uppsrc/plugin/jpg/lib/rdbmp.c | 57 +- uppsrc/plugin/jpg/lib/rdcolmap.c | 8 +- uppsrc/plugin/jpg/lib/rdjpgcom.c | 33 +- uppsrc/plugin/jpg/lib/rdppm.c | 17 +- uppsrc/plugin/jpg/lib/rdrle.c | 8 +- uppsrc/plugin/jpg/lib/rdswitch.c | 77 +- uppsrc/plugin/jpg/lib/rdtarga.c | 10 +- uppsrc/plugin/jpg/lib/transupp.c | 1329 ++++++-- uppsrc/plugin/jpg/lib/transupp.h | 142 +- uppsrc/plugin/jpg/lib/wrbmp.c | 6 +- uppsrc/plugin/jpg/lib/wrgif.c | 7 +- uppsrc/plugin/jpg/lib/wrjpgcom.c | 16 + uppsrc/plugin/jpg/lib/wrppm.c | 5 +- uppsrc/plugin/jpg/lib/wrrle.c | 2 +- uppsrc/plugin/jpg/lib/wrtarga.c | 5 +- uppsrc/plugin/wincert/pdf.cpp | 363 --- uppsrc/plugin/wincert/util.cpp | 163 - uppsrc/plugin/wincert/wincert.h | 34 - uppsrc/plugin/wincert/wincert.upp | 13 - 106 files changed, 19558 insertions(+), 10782 deletions(-) delete mode 100644 uppsrc/plugin/jpg/lib/ansi2knr.c create mode 100644 uppsrc/plugin/jpg/lib/jaricom.c create mode 100644 uppsrc/plugin/jpg/lib/jcarith.c delete mode 100644 uppsrc/plugin/jpg/lib/jcdiffct.c delete mode 100644 uppsrc/plugin/jpg/lib/jchuff.h delete mode 100644 uppsrc/plugin/jpg/lib/jclhuff.c delete mode 100644 uppsrc/plugin/jpg/lib/jclossls.c delete mode 100644 uppsrc/plugin/jpg/lib/jclossy.c delete mode 100644 uppsrc/plugin/jpg/lib/jcodec.c delete mode 100644 uppsrc/plugin/jpg/lib/jcphuff.c delete mode 100644 uppsrc/plugin/jpg/lib/jcpred.c delete mode 100644 uppsrc/plugin/jpg/lib/jcscale.c delete mode 100644 uppsrc/plugin/jpg/lib/jcshuff.c create mode 100644 uppsrc/plugin/jpg/lib/jdarith.c delete mode 100644 uppsrc/plugin/jpg/lib/jddiffct.c delete mode 100644 uppsrc/plugin/jpg/lib/jdhuff.h delete mode 100644 uppsrc/plugin/jpg/lib/jdlhuff.c delete mode 100644 uppsrc/plugin/jpg/lib/jdlossls.c delete mode 100644 uppsrc/plugin/jpg/lib/jdlossy.c delete mode 100644 uppsrc/plugin/jpg/lib/jdphuff.c delete mode 100644 uppsrc/plugin/jpg/lib/jdpred.c delete mode 100644 uppsrc/plugin/jpg/lib/jdscale.c delete mode 100644 uppsrc/plugin/jpg/lib/jdshuff.c delete mode 100644 uppsrc/plugin/jpg/lib/jidctred.c delete mode 100644 uppsrc/plugin/jpg/lib/jlossls.h delete mode 100644 uppsrc/plugin/jpg/lib/jlossy.h delete mode 100644 uppsrc/plugin/wincert/pdf.cpp delete mode 100644 uppsrc/plugin/wincert/util.cpp delete mode 100644 uppsrc/plugin/wincert/wincert.h delete mode 100644 uppsrc/plugin/wincert/wincert.upp diff --git a/uppsrc/ODBC/ODBC.cpp b/uppsrc/ODBC/ODBC.cpp index d92adc8fd..42ea1bfd4 100644 --- a/uppsrc/ODBC/ODBC.cpp +++ b/uppsrc/ODBC/ODBC.cpp @@ -461,6 +461,8 @@ bool ODBCConnection::Execute() return false; } Value v = param[pi++]; + if(session->charset >= 0 && IsString(v)) + v = ToCharset(session->charset, (String)v, CHARSET_DEFAULT, '?'); if(v.GetType() == 34) query.Cat(SqlCompile(MSSQL, ~SqlBinary(SqlRaw(v)))); else @@ -629,7 +631,10 @@ bool ODBCConnection::Fetch0() sb.SetLength(li); if(!IsOk(SQLGetData(session->hstmt, i + 1, ct, ~sb, li + 1, &li))) break; - v = String(sb); + String s = sb; + if(session->charset >= 0) + s = ToCharset(CHARSET_DEFAULT, s, session->charset, '?'); + v = s; } } break; diff --git a/uppsrc/ODBC/ODBC.h b/uppsrc/ODBC/ODBC.h index f10c1f27a..2da101ca8 100644 --- a/uppsrc/ODBC/ODBC.h +++ b/uppsrc/ODBC/ODBC.h @@ -45,6 +45,7 @@ private: String user; int tlevel; int tmode; + int charset = -1; void FlushConnections(); bool IsOk(SQLRETURN ret); @@ -61,6 +62,7 @@ public: }; void SetTransactionMode(int mode); + void Charset(int cs) { charset = cs; } ODBCSession(); ~ODBCSession(); diff --git a/uppsrc/Sql/Sqls.h b/uppsrc/Sql/Sqls.h index c2c1d0dd5..73bb8cf28 100644 --- a/uppsrc/Sql/Sqls.h +++ b/uppsrc/Sql/Sqls.h @@ -160,15 +160,16 @@ public: int GetColumns() const; int GetColumnCount() const; - void GetColumn(int i, Ref r) const; - void GetColumn(SqlId colid, Ref r) const; - Value operator[](int i) const; - Value operator[](SqlId colid) const; + void GetColumn(int i, Ref r) const; + void GetColumn(SqlId colid, Ref r) const; + Value operator[](int i) const; + Value operator[](SqlId colid) const; const SqlColumnInfo& GetColumnInfo(int i) const { return cn->info[i]; } - Vector GetRow() const; - ValueMap GetRowMap() const; - operator Vector() const { return GetRow(); } - void Get(Fields fields); + Vector GetRow() const; + operator Vector() const { return GetRow(); } + ValueMap GetRowMap() const; + ValueMap operator~() const { return GetRowMap(); } + void Get(Fields fields); void SetFetchRows(int nrows) { cn->fetchrows = nrows; } // deprecated void SetLongSize(int lsz) { cn->longsize = lsz; } // deprecated diff --git a/uppsrc/Sql/src.tpp/Sql$en-us.tpp b/uppsrc/Sql/src.tpp/Sql$en-us.tpp index ca68d8f08..f98764f40 100644 --- a/uppsrc/Sql/src.tpp/Sql$en-us.tpp +++ b/uppsrc/Sql/src.tpp/Sql$en-us.tpp @@ -168,9 +168,11 @@ Fetch.&] [s3; &] [s4; &] [s5;:Sql`:`:GetRowMap`(`)const:%- [_^ValueMap^ ValueMap]_[* GetRowMap]()_[@(0.0.255) const]&] +[s5;:Upp`:`:Sql`:`:operator`~`(`)const:%- [_^Upp`:`:ValueMap^ ValueMap]_[* operator`~]()_ +[@(0.0.255) const]&] [s2; Returns the whole fetched row, keys of ValueMap are names of columns. Only valid after successfull Fetch.&] -[s3; &] +[s3;%- &] [s4; &] [s5;:Sql`:`:operator Vector``(`)const:%- [* operator_Vector]()_[@(0.0.255) c onst]&] diff --git a/uppsrc/plugin/jpg/jpg.upp b/uppsrc/plugin/jpg/jpg.upp index a34e9e2f7..f4744e282 100644 --- a/uppsrc/plugin/jpg/jpg.upp +++ b/uppsrc/plugin/jpg/jpg.upp @@ -11,93 +11,75 @@ file jpgreg.icpp, src.tpp, lib readonly separator, + lib\jconfig.h, + lib\README, lib\cderror.h, - lib\cdjpeg.c, lib\cdjpeg.h, + lib\jdct.h, + lib\jerror.h, + lib\jinclude.h, + lib\jmemsys.h, + lib\jmorecfg.h, + lib\jpegint.h, + lib\jpeglib.h, + lib\jversion.h, + lib\transupp.h, + lib\cdjpeg.c, + lib\jaricom.c, lib\jcapimin.c, lib\jcapistd.c, + lib\jcarith.c, lib\jccoefct.c, lib\jccolor.c, lib\jcdctmgr.c, - lib\jcdiffct.c, lib\jchuff.c, - lib\jchuff.h, lib\jcinit.c, - lib\jclhuff.c, - lib\jclossls.c, - lib\jclossy.c, lib\jcmainct.c, lib\jcmarker.c, lib\jcmaster.c, - lib\jcodec.c, lib\jcomapi.c, - lib\jconfig.h, lib\jcparam.c, - lib\jcphuff.c, - lib\jcpred.c, lib\jcprepct.c, lib\jcsample.c, - lib\jcscale.c, - lib\jcshuff.c, lib\jctrans.c, lib\jdapimin.c, lib\jdapistd.c, + lib\jdarith.c, lib\jdatadst.c, lib\jdatasrc.c, lib\jdcoefct.c, lib\jdcolor.c, - lib\jdct.h, lib\jddctmgr.c, - lib\jddiffct.c, lib\jdhuff.c, - lib\jdhuff.h, lib\jdinput.c, - lib\jdlhuff.c, - lib\jdlossls.c, - lib\jdlossy.c, lib\jdmainct.c, lib\jdmarker.c, lib\jdmaster.c, lib\jdmerge.c, - lib\jdphuff.c, lib\jdpostct.c, - lib\jdpred.c, lib\jdsample.c, - lib\jdscale.c, - lib\jdshuff.c, lib\jdtrans.c, lib\jerror.c, - lib\jerror.h, lib\jfdctflt.c, lib\jfdctfst.c, lib\jfdctint.c, lib\jidctflt.c, lib\jidctfst.c, lib\jidctint.c, - lib\jidctred.c, - lib\jinclude.h, - lib\jlossls.h, - lib\jlossy.h, lib\jmemansi.c, lib\jmemmgr.c, - lib\jmemsys.h, - lib\jmorecfg.h, - lib\jpegint.h, - lib\jpeglib.h, lib\jquant1.c, lib\jquant2.c, lib\jutils.c, - lib\jversion.h, lib\rdbmp.c, lib\rdcolmap.c, lib\rdgif.c, + lib\rdjpgcom.c, lib\rdppm.c, lib\rdrle.c, lib\rdswitch.c, lib\rdtarga.c, - lib\README, lib\transupp.c, - lib\transupp.h, lib\wrbmp.c, lib\wrgif.c, lib\wrppm.c, diff --git a/uppsrc/plugin/jpg/lib/README b/uppsrc/plugin/jpg/lib/README index 911d0e843..0b5e09736 100644 --- a/uppsrc/plugin/jpg/lib/README +++ b/uppsrc/plugin/jpg/lib/README @@ -1,24 +1,20 @@ The Independent JPEG Group's JPEG software ========================================== -README for release 6b of 27-Mar-1998 +README for release 9b of 17-Jan-2016 ==================================== -This distribution contains the sixth public release of the Independent JPEG +This distribution contains the ninth public release of the Independent JPEG Group's free JPEG software. You are welcome to redistribute this software and to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. -Serious users of this software (particularly those incorporating it into -larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to -our electronic mailing list. Mailing list members are notified of updates -and have a chance to participate in technical discussions, etc. +This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone, +Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson, +Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers, +and other members of the Independent JPEG Group. -This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, -Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, -Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG -Group. - -IJG is not affiliated with the official ISO JPEG standards committee. +IJG is not affiliated with the ISO/IEC JTC1/SC29/WG1 standards committee +(previously known as JPEG, together with ITU-T SG16). DOCUMENTATION ROADMAP @@ -30,27 +26,27 @@ OVERVIEW General description of JPEG and the IJG software. LEGAL ISSUES Copyright, lack of warranty, terms of distribution. REFERENCES Where to learn more about JPEG. ARCHIVE LOCATIONS Where to find newer versions of this software. -RELATED SOFTWARE Other stuff you should get. +ACKNOWLEDGMENTS Special thanks. FILE FORMAT WARS Software *not* to get. TO DO Plans for future IJG releases. Other documentation files in the distribution are: User documentation: - install.doc How to configure and install the IJG software. - usage.doc Usage instructions for cjpeg, djpeg, jpegtran, + install.txt How to configure and install the IJG software. + usage.txt Usage instructions for cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom. - *.1 Unix-style man pages for programs (same info as usage.doc). - wizard.doc Advanced usage instructions for JPEG wizards only. + *.1 Unix-style man pages for programs (same info as usage.txt). + wizard.txt Advanced usage instructions for JPEG wizards only. change.log Version-to-version change highlights. Programmer and internal documentation: - libjpeg.doc How to use the JPEG library in your own programs. + libjpeg.txt How to use the JPEG library in your own programs. example.c Sample code for calling the JPEG library. - structure.doc Overview of the JPEG library's internal structure. - filelist.doc Road map of IJG files. - coderules.doc Coding style rules --- please read if you contribute code. + structure.txt Overview of the JPEG library's internal structure. + filelist.txt Road map of IJG files. + coderules.txt Coding style rules --- please read if you contribute code. -Please read at least the files install.doc and usage.doc. Useful information +Please read at least the files install.txt and usage.txt. Some information can also be found in the JPEG FAQ (Frequently Asked Questions) article. See ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. @@ -62,24 +58,15 @@ the order listed) before diving into the code. OVERVIEW ======== -This package contains C software to implement JPEG image compression and -decompression. JPEG (pronounced "jay-peg") is a standardized compression -method for full-color and gray-scale images. JPEG is intended for compressing -"real-world" scenes; line drawings, cartoons and other non-realistic images -are not its strong suit. JPEG is lossy, meaning that the output image is not -exactly identical to the input image. Hence you must not use JPEG if you -have to have identical output bits. However, on typical photographic images, -very good compression levels can be obtained with no visible change, and -remarkably high compression levels are possible if you can tolerate a -low-quality image. For more details, see the references, or just experiment -with various compression settings. +This package contains C software to implement JPEG image encoding, decoding, +and transcoding. JPEG (pronounced "jay-peg") is a standardized compression +method for full-color and grayscale images. This software implements JPEG baseline, extended-sequential, and progressive compression processes. Provision is made for supporting all variants of these processes, although some uncommon parameter settings aren't implemented yet. -For legal reasons, we are not distributing code for the arithmetic-coding -variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting -the hierarchical or lossless processes defined in the standard. +We have made no provision for supporting the hierarchical or lossless +processes defined in the standard. We provide a set of library routines for reading and writing JPEG image files, plus two sample applications "cjpeg" and "djpeg", which use the library to @@ -91,10 +78,11 @@ considerable functionality beyond the bare JPEG coding/decoding capability; for example, the color quantization modules are not strictly part of JPEG decoding, but they are essential for output to colormapped file formats or colormapped displays. These extra functions can be compiled out of the -library if not required for a particular application. We have also included -"jpegtran", a utility for lossless transcoding between different JPEG -processes, and "rdjpgcom" and "wrjpgcom", two simple applications for -inserting and extracting textual comments in JFIF files. +library if not required for a particular application. + +We have also included "jpegtran", a utility for lossless transcoding between +different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple +applications for inserting and extracting textual comments in JFIF files. The emphasis in designing this software has been on achieving portability and flexibility, while also making it fast enough to be useful. In particular, @@ -127,7 +115,7 @@ with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. -This software is copyright (C) 1991-1998, Thomas G. Lane. +This software is copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this @@ -158,47 +146,24 @@ commercial products, provided that all warranty or liability claims are assumed by the product vendor. -ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, -sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. -ansi2knr.c is NOT covered by the above copyright and conditions, but instead -by the usual distribution terms of the Free Software Foundation; principally, -that you must include source code if you redistribute it. (See the file -ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part -of any program generated from the IJG code, this does not limit you more than -the foregoing paragraphs do. - The Unix configuration script "configure" was produced with GNU Autoconf. It is copyright by the Free Software Foundation but is freely distributable. The same holds for its supporting scripts (config.guess, config.sub, -ltconfig, ltmain.sh). Another support script, install-sh, is copyright -by M.I.T. but is also freely distributable. - -It appears that the arithmetic coding option of the JPEG spec is covered by -patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot -legally be used without obtaining one or more licenses. For this reason, -support for arithmetic coding has been removed from the free JPEG software. -(Since arithmetic coding provides only a marginal gain over the unpatented -Huffman mode, it is unlikely that very many implementations will support it.) -So far as we are aware, there are no patent restrictions on the remaining -code. +ltmain.sh). Another support script, install-sh, is copyright by X Consortium +but is also freely distributable. The IJG distribution formerly included code to read and write GIF files. -To avoid entanglement with the Unisys LZW patent, GIF reading support has -been removed altogether, and the GIF writer has been simplified to produce -"uncompressed GIFs". This technique does not use the LZW algorithm; the -resulting GIF files are larger than usual, but are readable by all standard -GIF decoders. - -We are required to state that - "The Graphics Interchange Format(c) is the Copyright property of - CompuServe Incorporated. GIF(sm) is a Service Mark property of - CompuServe Incorporated." +To avoid entanglement with the Unisys LZW patent (now expired), GIF reading +support has been removed altogether, and the GIF writer has been simplified +to produce "uncompressed GIFs". This technique does not use the LZW +algorithm; the resulting GIF files are larger than usual, but are readable +by all standard GIF decoders. REFERENCES ========== -We highly recommend reading one or more of these references before trying to +We recommend reading one or more of these references before trying to understand the innards of the JPEG software. The best short technical introduction to the JPEG compression algorithm is @@ -206,8 +171,8 @@ The best short technical introduction to the JPEG compression algorithm is Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. (Adjacent articles in that issue discuss MPEG motion picture compression, applications of JPEG, and related topics.) If you don't have the CACM issue -handy, a PostScript file containing a revised version of Wallace's article is -available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually +handy, a PDF file containing a revised version of Wallace's article is +available at http://www.ijg.org/files/Wallace.JPEG.pdf. The file (actually a preprint for an article that appeared in IEEE Trans. Consumer Electronics) omits the sample images that appeared in CACM, but it includes corrections and some added material. Note: the Wallace article is copyright ACM and IEEE, @@ -222,82 +187,70 @@ code but don't know much about data compression in general. The book's JPEG sample code is far from industrial-strength, but when you are ready to look at a full implementation, you've got one here... -The best full description of JPEG is the textbook "JPEG Still Image Data -Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published -by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. -The book includes the complete text of the ISO JPEG standards (DIS 10918-1 -and draft DIS 10918-2). This is by far the most complete exposition of JPEG -in existence, and we highly recommend it. +The best currently available description of JPEG is the textbook "JPEG Still +Image Data Compression Standard" by William B. Pennebaker and Joan L. +Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. +Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG +standards (DIS 10918-1 and draft DIS 10918-2). +Although this is by far the most detailed and comprehensive exposition of +JPEG publicly available, we point out that it is still missing an explanation +of the most essential properties and algorithms of the underlying DCT +technology. +If you think that you know about DCT-based JPEG after reading this book, +then you are in delusion. The real fundamentals and corresponding potential +of DCT-based JPEG are not publicly known so far, and that is the reason for +all the mistaken developments taking place in the image coding domain. -The JPEG standard itself is not available electronically; you must order a -paper copy through ISO or ITU. (Unless you feel a need to own a certified -official copy, we recommend buying the Pennebaker and Mitchell book instead; -it's much cheaper and includes a great deal of useful explanatory material.) -In the USA, copies of the standard may be ordered from ANSI Sales at (212) -642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI -doesn't take credit card orders, but Global does.) It's not cheap: as of -1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% -shipping/handling. The standard is divided into two parts, Part 1 being the -actual specification, while Part 2 covers compliance testing methods. Part 1 -is titled "Digital Compression and Coding of Continuous-tone Still Images, +The original JPEG standard is divided into two parts, Part 1 being the actual +specification, while Part 2 covers compliance testing methods. Part 1 is +titled "Digital Compression and Coding of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS 10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and has document numbers ISO/IEC IS 10918-2, ITU-T T.83. - -Some extensions to the original JPEG standard are defined in JPEG Part 3, -a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG -currently does not support any Part 3 extensions. +IJG JPEG 8 introduced an implementation of the JPEG SmartScale extension +which is specified in two documents: A contributed document at ITU and ISO +with title "ITU-T JPEG-Plus Proposal for Extending ITU-T T.81 for Advanced +Image Coding", April 2006, Geneva, Switzerland. The latest version of this +document is Revision 3. And a contributed document ISO/IEC JTC1/SC29/WG1 N +5799 with title "Evolution of JPEG", June/July 2011, Berlin, Germany. +IJG JPEG 9 introduces a reversible color transform for improved lossless +compression which is described in a contributed document ISO/IEC JTC1/SC29/ +WG1 N 6080 with title "JPEG 9 Lossless Coding", June/July 2012, Paris, +France. The JPEG standard does not specify all details of an interchangeable file -format. For the omitted details we follow the "JFIF" conventions, revision -1.02. A copy of the JFIF spec is available from: - Literature Department - C-Cube Microsystems, Inc. - 1778 McCarthy Blvd. - Milpitas, CA 95035 - phone (408) 944-6300, fax (408) 944-6314 -A PostScript version of this document is available by FTP at -ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text -version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing -the figures. +format. For the omitted details we follow the "JFIF" conventions, version 2. +JFIF version 1 has been adopted as Recommendation ITU-T T.871 (05/2011) : +Information technology - Digital compression and coding of continuous-tone +still images: JPEG File Interchange Format (JFIF). It is available as a +free download in PDF file format from http://www.itu.int/rec/T-REC-T.871. +A PDF file of the older JFIF document is available at +http://www.w3.org/Graphics/JPEG/jfif3.pdf. The TIFF 6.0 file format specification can be obtained by FTP from ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 -(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or -from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision +(Compression tag 7). Copies of this Note can be obtained from +http://www.ijg.org/files/. It is expected that the next revision of the TIFF spec will replace the 6.0 JPEG design with the Note's design. Although IJG's own code does not support TIFF/JPEG, the free libtiff library -uses our library to implement TIFF/JPEG per the Note. libtiff is available -from ftp://ftp.sgi.com/graphics/tiff/. +uses our library to implement TIFF/JPEG per the Note. ARCHIVE LOCATIONS ================= -The "official" archive site for this software is ftp.uu.net (Internet -address 192.48.96.9). The most recent released version can always be found -there in directory graphics/jpeg. This particular version will be archived -as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have -direct Internet access, UUNET's archives are also available via UUCP; contact -help@uunet.uu.net for information on retrieving files that way. +The "official" archive site for this software is www.ijg.org. +The most recent released version can always be found there in +directory "files". This particular version will be archived as +http://www.ijg.org/files/jpegsrc.v9b.tar.gz, and in Windows-compatible +"zip" archive format as http://www.ijg.org/files/jpegsr9b.zip. -Numerous Internet sites maintain copies of the UUNET files. However, only -ftp.uu.net is guaranteed to have the latest official version. - -You can also obtain this software in DOS-compatible "zip" archive format from -the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or -on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 -"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net -release. - -The JPEG FAQ (Frequently Asked Questions) article is a useful source of -general information about JPEG. It is updated constantly and therefore is -not included in this distribution. The FAQ is posted every two weeks to -Usenet newsgroups comp.graphics.misc, news.answers, and other groups. +The JPEG FAQ (Frequently Asked Questions) article is a source of some +general information about JPEG. It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ and other news.answers archive sites, including the official news.answers archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. @@ -307,79 +260,116 @@ with body send usenet/news.answers/jpeg-faq/part2 -RELATED SOFTWARE -================ +ACKNOWLEDGMENTS +=============== -Numerous viewing and image manipulation programs now support JPEG. (Quite a -few of them use this library to do so.) The JPEG FAQ described above lists -some of the more popular free and shareware viewers, and tells where to -obtain them on Internet. +Thank to Juergen Bruder for providing me with a copy of the common DCT +algorithm article, only to find out that I had come to the same result +in a more direct and comprehensible way with a more generative approach. -If you are on a Unix machine, we highly recommend Jef Poskanzer's free -PBMPLUS software, which provides many useful operations on PPM-format image -files. In particular, it can convert PPM images to and from a wide range of -other formats, thus making cjpeg/djpeg considerably more useful. The latest -version is distributed by the NetPBM group, and is available from numerous -sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. -Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; -you are likely to have difficulty making it work on any non-Unix machine. +Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the +ITU JPEG (Study Group 16) meeting in Geneva, Switzerland. -A different free JPEG implementation, written by the PVRG group at Stanford, -is available from ftp://havefun.stanford.edu/pub/jpeg/. This program -is designed for research and experimentation rather than production use; -it is slower, harder to use, and less portable than the IJG code, but it -is easier to read and modify. Also, the PVRG code supports lossless JPEG, -which we do not. (On the other hand, it doesn't do progressive JPEG.) +Thank to Thomas Wiegand and Gary Sullivan for inviting me to the +Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland. + +Thank to Thomas Richter and Daniel Lee for inviting me to the +ISO/IEC JTC1/SC29/WG1 (previously known as JPEG, together with ITU-T SG16) +meeting in Berlin, Germany. + +Thank to John Korejwa and Massimo Ballerini for inviting me to +fruitful consultations in Boston, MA and Milan, Italy. + +Thank to Hendrik Elstner, Roland Fassauer, Simone Zuck, Guenther +Maier-Gerber, Walter Stoeber, Fred Schmitz, and Norbert Braunagel +for corresponding business development. + +Thank to Nico Zschach and Dirk Stelling of the technical support team +at the Digital Images company in Halle for providing me with extra +equipment for configuration tests. + +Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful +communication about JPEG configuration in Sigma Photo Pro software. + +Thank to Andrew Finkenstadt for hosting the ijg.org site. + +Last but not least special thank to Thomas G. Lane for the original +design and development of this singular software package. FILE FORMAT WARS ================ -Some JPEG programs produce files that are not compatible with our library. -The root of the problem is that the ISO JPEG committee failed to specify a -concrete file format. Some vendors "filled in the blanks" on their own, -creating proprietary formats that no one else could read. (For example, none -of the early commercial JPEG implementations for the Macintosh were able to -exchange compressed files.) +The ISO/IEC JTC1/SC29/WG1 standards committee (previously known as JPEG, +together with ITU-T SG16) currently promotes different formats containing +the name "JPEG" which is misleading because these formats are incompatible +with original DCT-based JPEG and are based on faulty technologies. +IJG therefore does not and will not support such momentary mistakes +(see REFERENCES). +There exist also distributions under the name "OpenJPEG" promoting such +kind of formats which is misleading because they don't support original +JPEG images. +We have no sympathy for the promotion of inferior formats. Indeed, one of +the original reasons for developing this free software was to help force +convergence on common, interoperable format standards for JPEG files. +Don't use an incompatible file format! +(In any case, our decoder will remain capable of reading existing JPEG +image files indefinitely.) -The file format we have adopted is called JFIF (see REFERENCES). This format -has been agreed to by a number of major commercial JPEG vendors, and it has -become the de facto standard. JFIF is a minimal or "low end" representation. -We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF -Technical Note #2) for "high end" applications that need to record a lot of -additional data about an image. TIFF/JPEG is fairly new and not yet widely -supported, unfortunately. +The ISO committee pretends to be "responsible for the popular JPEG" in their +public reports which is not true because they don't respond to actual +requirements for the maintenance of the original JPEG specification. +Furthermore, the ISO committee pretends to "ensure interoperability" with +their standards which is not true because their "standards" support only +application-specific and proprietary use cases and contain mathematically +incorrect code. -The upcoming JPEG Part 3 standard defines a file format called SPIFF. -SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should -be able to read the most common variant of SPIFF. SPIFF has some technical -advantages over JFIF, but its major claim to fame is simply that it is an -official standard rather than an informal one. At this point it is unclear -whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto -standard. IJG intends to support SPIFF once the standard is frozen, but we -have not decided whether it should become our default output format or not. -(In any case, our decoder will remain capable of reading JFIF indefinitely.) +There are currently different distributions in circulation containing the +name "libjpeg" which is misleading because they don't have the features and +are incompatible with formats supported by actual IJG libjpeg distributions. +One of those fakes is released by members of the ISO committee and just uses +the name of libjpeg for misdirection of people, similar to the abuse of the +name JPEG as described above, while having nothing in common with actual IJG +libjpeg distributions and containing mathematically incorrect code. +The other one claims to be a "derivative" or "fork" of the original libjpeg, +but violates the license conditions as described under LEGAL ISSUES above +and violates basic C programming properties. +We have no sympathy for the release of misleading, incorrect and illegal +distributions derived from obsolete code bases. +Don't use an obsolete code base! -Various proprietary file formats incorporating JPEG compression also exist. -We have little or no sympathy for the existence of these formats. Indeed, -one of the original reasons for developing this free software was to help -force convergence on common, open format standards for JPEG files. Don't -use a proprietary file format! +According to the UCC (Uniform Commercial Code) law, IJG has the lawful and +legal right to foreclose on certain standardization bodies and other +institutions or corporations that knowingly perform substantial and +systematic deceptive acts and practices, fraud, theft, and damaging of the +value of the people of this planet without their knowing, willing and +intentional consent. +The titles, ownership, and rights of these institutions and all their assets +are now duly secured and held in trust for the free people of this planet. +People of the planet, on every country, may have a financial interest in +the assets of these former principals, agents, and beneficiaries of the +foreclosed institutions and corporations. +IJG asserts what is: that each man, woman, and child has unalienable value +and rights granted and deposited in them by the Creator and not any one of +the people is subordinate to any artificial principality, corporate fiction +or the special interest of another without their appropriate knowing, +willing and intentional consent made by contract or accommodation agreement. +IJG expresses that which already was. +The people have already determined and demanded that public administration +entities, national governments, and their supporting judicial systems must +be fully transparent, accountable, and liable. +IJG has secured the value for all concerned free people of the planet. + +A partial list of foreclosed institutions and corporations ("Hall of Shame") +is currently prepared and will be published later. TO DO ===== -The major thrust for v7 will probably be improvement of visual quality. -The current method for scaling the quantization tables is known not to be -very good at low Q values. We also intend to investigate block boundary -smoothing, "poor man's variable quantization", and other means of improving -quality-vs-file-size performance without sacrificing compatibility. +Version 9 is the second release of a new generation JPEG standard +to overcome the limitations of the original JPEG specification, +and is the first true source reference JPEG codec. +More features are being prepared for coming releases... -In future versions, we are considering supporting some of the upcoming JPEG -Part 3 extensions --- principally, variable quantization and the SPIFF file -format. - -As always, speeding things up is of great interest. - -Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. +Please send bug reports, offers of help, etc. to jpeg-info@jpegclub.org. diff --git a/uppsrc/plugin/jpg/lib/ansi2knr.c b/uppsrc/plugin/jpg/lib/ansi2knr.c deleted file mode 100644 index 0e3ab134a..000000000 --- a/uppsrc/plugin/jpg/lib/ansi2knr.c +++ /dev/null @@ -1,693 +0,0 @@ -/* ansi2knr.c */ -/* Convert ANSI C function definitions to K&R ("traditional C") syntax */ - -/* -ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone for the -consequences of using it or for whether it serves any particular purpose or -works at all, unless he says so in writing. Refer to the GNU General Public -License (the "GPL") for full details. - -Everyone is granted permission to copy, modify and redistribute ansi2knr, -but only under the conditions described in the GPL. A copy of this license -is supposed to have been given to you along with ansi2knr so you can know -your rights and responsibilities. It should be in a file named COPYLEFT. -[In the IJG distribution, the GPL appears below, not in a separate file.] -Among other things, the copyright notice and this notice must be preserved -on all copies. - -We explicitly state here what we believe is already implied by the GPL: if -the ansi2knr program is distributed as a separate set of sources and a -separate executable file which are aggregated on a storage medium together -with another program, this in itself does not bring the other program under -the GPL, nor does the mere fact that such a program or the procedures for -constructing it invoke the ansi2knr executable bring any other part of the -program under the GPL. -*/ - -/* ----------- Here is the GNU GPL file COPYLEFT, referred to above ---------- ------ These terms do NOT apply to the JPEG software itself; see README ------ - - GHOSTSCRIPT GENERAL PUBLIC LICENSE - (Clarified 11 Feb 1988) - - Copyright (C) 1988 Richard M. Stallman - Everyone is permitted to copy and distribute verbatim copies of this - license, but changing it is not allowed. You can also use this wording - to make the terms for other programs. - - The license agreements of most software companies keep you at the -mercy of those companies. By contrast, our general public license is -intended to give everyone the right to share Ghostscript. To make sure -that you get the rights we want you to have, we need to make -restrictions that forbid anyone to deny you these rights or to ask you -to surrender the rights. Hence this license agreement. - - Specifically, we want to make sure that you have the right to give -away copies of Ghostscript, that you receive source code or else can get -it if you want it, that you can change Ghostscript or use pieces of it -in new free programs, and that you know you can do these things. - - To make sure that everyone has such rights, we have to forbid you to -deprive anyone else of these rights. For example, if you distribute -copies of Ghostscript, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must tell them their rights. - - Also, for our own protection, we must make certain that everyone finds -out that there is no warranty for Ghostscript. If Ghostscript is -modified by someone else and passed on, we want its recipients to know -that what they have is not what we distributed, so that any problems -introduced by others will not reflect on our reputation. - - Therefore we (Richard M. Stallman and the Free Software Foundation, -Inc.) make the following terms which say what you must do to be allowed -to distribute or change Ghostscript. - - - COPYING POLICIES - - 1. You may copy and distribute verbatim copies of Ghostscript source -code as you receive it, in any medium, provided that you conspicuously -and appropriately publish on each copy a valid copyright and license -notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved. -Distributed by Free Software Foundation, Inc." (or with whatever year is -appropriate); keep intact the notices on all files that refer to this -License Agreement and to the absence of any warranty; and give any other -recipients of the Ghostscript program a copy of this License Agreement -along with the program. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of Ghostscript or any portion of -it, and copy and distribute such modifications under the terms of -Paragraph 1 above, provided that you also do the following: - - a) cause the modified files to carry prominent notices stating - that you changed the files and the date of any change; and - - b) cause the whole of any work that you distribute or publish, - that in whole or in part contains or is a derivative of Ghostscript - or any part thereof, to be licensed at no charge to all third - parties on terms identical to those contained in this License - Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution fee for the physical act of - transferring a copy, and you may at your option offer warranty - protection in exchange for a fee. - -Mere aggregation of another unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute Ghostscript (or a portion or derivative -of it, under Paragraph 2) in object code or executable form under the -terms of Paragraphs 1 and 2 above provided that you also do one of the -following: - - a) accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of - Paragraphs 1 and 2 above; or, - - b) accompany it with a written offer, valid for at least three - years, to give any third party free (except for a nominal - shipping charge) a complete machine-readable copy of the - corresponding source code, to be distributed under the terms of - Paragraphs 1 and 2 above; or, - - c) accompany it with the information you received as to where the - corresponding source code may be obtained. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form alone.) - -For an executable file, complete source code means all the source code for -all modules it contains; but, as a special exception, it need not include -source code for modules which are standard libraries that accompany the -operating system on which the executable file runs. - - 4. You may not copy, sublicense, distribute or transfer Ghostscript -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer Ghostscript is -void and your rights to use the program under this License agreement -shall be automatically terminated. However, parties who have received -computer software programs from you with this License Agreement will not -have their licenses terminated so long as such parties remain in full -compliance. - - 5. If you wish to incorporate parts of Ghostscript into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not -yet worked out a simple rule that can be stated here, but we will often -permit this. We will be guided by the two goals of preserving the free -status of all derivatives of our free software and of promoting the -sharing and reuse of software. - -Your comments and suggestions about our licensing policies and our -software are welcome! Please contact the Free Software Foundation, -Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296. - - NO WARRANTY - - BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD -M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES -PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE -ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH -YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL -NECESSARY SERVICING, REPAIR OR CORRECTION. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN -ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE -GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING -ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE -(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED -INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE -PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU -HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM -BY ANY OTHER PARTY. - --------------------- End of file COPYLEFT ------------------------------ -*/ - -/* - * Usage: - ansi2knr input_file [output_file] - * If no output_file is supplied, output goes to stdout. - * There are no error messages. - * - * ansi2knr recognizes function definitions by seeing a non-keyword - * identifier at the left margin, followed by a left parenthesis, - * with a right parenthesis as the last character on the line, - * and with a left brace as the first token on the following line - * (ignoring possible intervening comments). - * It will recognize a multi-line header provided that no intervening - * line ends with a left or right brace or a semicolon. - * These algorithms ignore whitespace and comments, except that - * the function name must be the first thing on the line. - * The following constructs will confuse it: - * - Any other construct that starts at the left margin and - * follows the above syntax (such as a macro or function call). - * - Some macros that tinker with the syntax of the function header. - */ - -/* - * The original and principal author of ansi2knr is L. Peter Deutsch - * . Other authors are noted in the change history - * that follows (in reverse chronological order): - lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with - compilers that don't understand void, as suggested by - Tom Lane - lpd 96-01-15 changed to require that the first non-comment token - on the line following a function header be a left brace, - to reduce sensitivity to macros, as suggested by Tom Lane - - lpd 95-06-22 removed #ifndefs whose sole purpose was to define - undefined preprocessor symbols as 0; changed all #ifdefs - for configuration symbols to #ifs - lpd 95-04-05 changed copyright notice to make it clear that - including ansi2knr in a program does not bring the entire - program under the GPL - lpd 94-12-18 added conditionals for systems where ctype macros - don't handle 8-bit characters properly, suggested by - Francois Pinard ; - removed --varargs switch (this is now the default) - lpd 94-10-10 removed CONFIG_BROKETS conditional - lpd 94-07-16 added some conditionals to help GNU `configure', - suggested by Francois Pinard ; - properly erase prototype args in function parameters, - contributed by Jim Avera ; - correct error in writeblanks (it shouldn't erase EOLs) - lpd 89-xx-xx original version - */ - -/* Most of the conditionals here are to make ansi2knr work with */ -/* or without the GNU configure machinery. */ - -#if HAVE_CONFIG_H -# include -#endif - -#include -#include - -#if HAVE_CONFIG_H - -/* - For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h). - This will define HAVE_CONFIG_H and so, activate the following lines. - */ - -# if STDC_HEADERS || HAVE_STRING_H -# include -# else -# include -# endif - -#else /* not HAVE_CONFIG_H */ - -/* Otherwise do it the hard way */ - -# ifdef BSD -# include -# else -# ifdef VMS - extern int strlen(), strncmp(); -# else -# include -# endif -# endif - -#endif /* not HAVE_CONFIG_H */ - -#if STDC_HEADERS -# include -#else -/* - malloc and free should be declared in stdlib.h, - but if you've got a K&R compiler, they probably aren't. - */ -# ifdef MSDOS -# include -# else -# ifdef VMS - extern char *malloc(); - extern void free(); -# else - extern char *malloc(); - extern int free(); -# endif -# endif - -#endif - -/* - * The ctype macros don't always handle 8-bit characters correctly. - * Compensate for this here. - */ -#ifdef isascii -# undef HAVE_ISASCII /* just in case */ -# define HAVE_ISASCII 1 -#else -#endif -#if STDC_HEADERS || !HAVE_ISASCII -# define is_ascii(c) 1 -#else -# define is_ascii(c) isascii(c) -#endif - -#define is_space(c) (is_ascii(c) && isspace(c)) -#define is_alpha(c) (is_ascii(c) && isalpha(c)) -#define is_alnum(c) (is_ascii(c) && isalnum(c)) - -/* Scanning macros */ -#define isidchar(ch) (is_alnum(ch) || (ch) == '_') -#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_') - -/* Forward references */ -char *skipspace(); -int writeblanks(); -int test1(); -int convert1(); - -/* The main program */ -int -main(argc, argv) - int argc; - char *argv[]; -{ FILE *in, *out; -#define bufsize 5000 /* arbitrary size */ - char *buf; - char *line; - char *more; - /* - * In previous versions, ansi2knr recognized a --varargs switch. - * If this switch was supplied, ansi2knr would attempt to convert - * a ... argument to va_alist and va_dcl; if this switch was not - * supplied, ansi2knr would simply drop any such arguments. - * Now, ansi2knr always does this conversion, and we only - * check for this switch for backward compatibility. - */ - int convert_varargs = 1; - - if ( argc > 1 && argv[1][0] == '-' ) - { if ( !strcmp(argv[1], "--varargs") ) - { convert_varargs = 1; - argc--; - argv++; - } - else - { fprintf(stderr, "Unrecognized switch: %s\n", argv[1]); - exit(1); - } - } - switch ( argc ) - { - default: - printf("Usage: ansi2knr input_file [output_file]\n"); - exit(0); - case 2: - out = stdout; - break; - case 3: - out = fopen(argv[2], "w"); - if ( out == NULL ) - { fprintf(stderr, "Cannot open output file %s\n", argv[2]); - exit(1); - } - } - in = fopen(argv[1], "r"); - if ( in == NULL ) - { fprintf(stderr, "Cannot open input file %s\n", argv[1]); - exit(1); - } - fprintf(out, "#line 1 \"%s\"\n", argv[1]); - buf = malloc(bufsize); - line = buf; - while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) - { -test: line += strlen(line); - switch ( test1(buf) ) - { - case 2: /* a function header */ - convert1(buf, out, 1, convert_varargs); - break; - case 1: /* a function */ - /* Check for a { at the start of the next line. */ - more = ++line; -f: if ( line >= buf + (bufsize - 1) ) /* overflow check */ - goto wl; - if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL ) - goto wl; - switch ( *skipspace(more, 1) ) - { - case '{': - /* Definitely a function header. */ - convert1(buf, out, 0, convert_varargs); - fputs(more, out); - break; - case 0: - /* The next line was blank or a comment: */ - /* keep scanning for a non-comment. */ - line += strlen(line); - goto f; - default: - /* buf isn't a function header, but */ - /* more might be. */ - fputs(buf, out); - strcpy(buf, more); - line = buf; - goto test; - } - break; - case -1: /* maybe the start of a function */ - if ( line != buf + (bufsize - 1) ) /* overflow check */ - continue; - /* falls through */ - default: /* not a function */ -wl: fputs(buf, out); - break; - } - line = buf; - } - if ( line != buf ) - fputs(buf, out); - free(buf); - fclose(out); - fclose(in); - return 0; -} - -/* Skip over space and comments, in either direction. */ -char * -skipspace(p, dir) - register char *p; - register int dir; /* 1 for forward, -1 for backward */ -{ for ( ; ; ) - { while ( is_space(*p) ) - p += dir; - if ( !(*p == '/' && p[dir] == '*') ) - break; - p += dir; p += dir; - while ( !(*p == '*' && p[dir] == '/') ) - { if ( *p == 0 ) - return p; /* multi-line comment?? */ - p += dir; - } - p += dir; p += dir; - } - return p; -} - -/* - * Write blanks over part of a string. - * Don't overwrite end-of-line characters. - */ -int -writeblanks(start, end) - char *start; - char *end; -{ char *p; - for ( p = start; p < end; p++ ) - if ( *p != '\r' && *p != '\n' ) - *p = ' '; - return 0; -} - -/* - * Test whether the string in buf is a function definition. - * The string may contain and/or end with a newline. - * Return as follows: - * 0 - definitely not a function definition; - * 1 - definitely a function definition; - * 2 - definitely a function prototype (NOT USED); - * -1 - may be the beginning of a function definition, - * append another line and look again. - * The reason we don't attempt to convert function prototypes is that - * Ghostscript's declaration-generating macros look too much like - * prototypes, and confuse the algorithms. - */ -int -test1(buf) - char *buf; -{ register char *p = buf; - char *bend; - char *endfn; - int contin; - - if ( !isidfirstchar(*p) ) - return 0; /* no name at left margin */ - bend = skipspace(buf + strlen(buf) - 1, -1); - switch ( *bend ) - { - case ';': contin = 0 /*2*/; break; - case ')': contin = 1; break; - case '{': return 0; /* not a function */ - case '}': return 0; /* not a function */ - default: contin = -1; - } - while ( isidchar(*p) ) - p++; - endfn = p; - p = skipspace(p, 1); - if ( *p++ != '(' ) - return 0; /* not a function */ - p = skipspace(p, 1); - if ( *p == ')' ) - return 0; /* no parameters */ - /* Check that the apparent function name isn't a keyword. */ - /* We only need to check for keywords that could be followed */ - /* by a left parenthesis (which, unfortunately, is most of them). */ - { static char *words[] = - { "asm", "auto", "case", "char", "const", "double", - "extern", "float", "for", "if", "int", "long", - "register", "return", "short", "signed", "sizeof", - "static", "switch", "typedef", "unsigned", - "void", "volatile", "while", 0 - }; - char **key = words; - char *kp; - int len = endfn - buf; - - while ( (kp = *key) != 0 ) - { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) - return 0; /* name is a keyword */ - key++; - } - } - return contin; -} - -/* Convert a recognized function definition or header to K&R syntax. */ -int -convert1(buf, out, header, convert_varargs) - char *buf; - FILE *out; - int header; /* Boolean */ - int convert_varargs; /* Boolean */ -{ char *endfn; - register char *p; - char **breaks; - unsigned num_breaks = 2; /* for testing */ - char **btop; - char **bp; - char **ap; - char *vararg = 0; - - /* Pre-ANSI implementations don't agree on whether strchr */ - /* is called strchr or index, so we open-code it here. */ - for ( endfn = buf; *(endfn++) != '('; ) - ; -top: p = endfn; - breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); - if ( breaks == 0 ) - { /* Couldn't allocate break table, give up */ - fprintf(stderr, "Unable to allocate break table!\n"); - fputs(buf, out); - return -1; - } - btop = breaks + num_breaks * 2 - 2; - bp = breaks; - /* Parse the argument list */ - do - { int level = 0; - char *lp = NULL; - char *rp; - char *end = NULL; - - if ( bp >= btop ) - { /* Filled up break table. */ - /* Allocate a bigger one and start over. */ - free((char *)breaks); - num_breaks <<= 1; - goto top; - } - *bp++ = p; - /* Find the end of the argument */ - for ( ; end == NULL; p++ ) - { switch(*p) - { - case ',': - if ( !level ) end = p; - break; - case '(': - if ( !level ) lp = p; - level++; - break; - case ')': - if ( --level < 0 ) end = p; - else rp = p; - break; - case '/': - p = skipspace(p, 1) - 1; - break; - default: - ; - } - } - /* Erase any embedded prototype parameters. */ - if ( lp ) - writeblanks(lp + 1, rp); - p--; /* back up over terminator */ - /* Find the name being declared. */ - /* This is complicated because of procedure and */ - /* array modifiers. */ - for ( ; ; ) - { p = skipspace(p - 1, -1); - switch ( *p ) - { - case ']': /* skip array dimension(s) */ - case ')': /* skip procedure args OR name */ - { int level = 1; - while ( level ) - switch ( *--p ) - { - case ']': case ')': level++; break; - case '[': case '(': level--; break; - case '/': p = skipspace(p, -1) + 1; break; - default: ; - } - } - if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) - { /* We found the name being declared */ - while ( !isidfirstchar(*p) ) - p = skipspace(p, 1) + 1; - goto found; - } - break; - default: - goto found; - } - } -found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) - { if ( convert_varargs ) - { *bp++ = "va_alist"; - vararg = p-2; - } - else - { p++; - if ( bp == breaks + 1 ) /* sole argument */ - writeblanks(breaks[0], p); - else - writeblanks(bp[-1] - 1, p); - bp--; - } - } - else - { while ( isidchar(*p) ) p--; - *bp++ = p+1; - } - p = end; - } - while ( *p++ == ',' ); - *bp = p; - /* Make a special check for 'void' arglist */ - if ( bp == breaks+2 ) - { p = skipspace(breaks[0], 1); - if ( !strncmp(p, "void", 4) ) - { p = skipspace(p+4, 1); - if ( p == breaks[2] - 1 ) - { bp = breaks; /* yup, pretend arglist is empty */ - writeblanks(breaks[0], p + 1); - } - } - } - /* Put out the function name and left parenthesis. */ - p = buf; - while ( p != endfn ) putc(*p, out), p++; - /* Put out the declaration. */ - if ( header ) - { fputs(");", out); - for ( p = breaks[0]; *p; p++ ) - if ( *p == '\r' || *p == '\n' ) - putc(*p, out); - } - else - { for ( ap = breaks+1; ap < bp; ap += 2 ) - { p = *ap; - while ( isidchar(*p) ) - putc(*p, out), p++; - if ( ap < bp - 1 ) - fputs(", ", out); - } - fputs(") ", out); - /* Put out the argument declarations */ - for ( ap = breaks+2; ap <= bp; ap += 2 ) - (*ap)[-1] = ';'; - if ( vararg != 0 ) - { *vararg = 0; - fputs(breaks[0], out); /* any prior args */ - fputs("va_dcl", out); /* the final arg */ - fputs(bp[0], out); - } - else - fputs(breaks[0], out); - } - free((char *)breaks); - return 0; -} diff --git a/uppsrc/plugin/jpg/lib/cderror.h b/uppsrc/plugin/jpg/lib/cderror.h index c19d38fb4..fb72a51f6 100644 --- a/uppsrc/plugin/jpg/lib/cderror.h +++ b/uppsrc/plugin/jpg/lib/cderror.h @@ -2,6 +2,7 @@ * cderror.h * * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -45,6 +46,7 @@ JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") +JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image") JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") diff --git a/uppsrc/plugin/jpg/lib/cdjpeg.h b/uppsrc/plugin/jpg/lib/cdjpeg.h index 1574e0b1f..c0d064cca 100644 --- a/uppsrc/plugin/jpg/lib/cdjpeg.h +++ b/uppsrc/plugin/jpg/lib/cdjpeg.h @@ -104,6 +104,7 @@ typedef struct cdjpeg_progress_mgr * cd_progress_ptr; #define jinit_write_targa jIWrTarga #define read_quant_tables RdQTables #define read_scan_script RdScnScript +#define set_quality_ratings SetQRates #define set_quant_slots SetQSlots #define set_sample_factors SetSFacts #define read_color_map RdCMap @@ -131,8 +132,10 @@ EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); /* cjpeg support routines (in rdswitch.c) */ EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, - int scale_factor, boolean force_baseline)); + boolean force_baseline)); EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); +EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg, + boolean force_baseline)); EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); diff --git a/uppsrc/plugin/jpg/lib/cjpeg.c b/uppsrc/plugin/jpg/lib/cjpeg.c index 45ab8bd9f..b9b65b883 100644 --- a/uppsrc/plugin/jpg/lib/cjpeg.c +++ b/uppsrc/plugin/jpg/lib/cjpeg.c @@ -2,6 +2,7 @@ * cjpeg.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -149,21 +150,32 @@ usage (void) #endif fprintf(stderr, "Switches (names may be abbreviated):\n"); - fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n"); + fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is useful range)\n"); fprintf(stderr, " -grayscale Create monochrome JPEG file\n"); + fprintf(stderr, " -rgb Create RGB JPEG file\n"); #ifdef ENTROPY_OPT_SUPPORTED fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); #endif #ifdef C_PROGRESSIVE_SUPPORTED fprintf(stderr, " -progressive Create progressive JPEG file\n"); #endif -#ifdef C_LOSSLESS_SUPPORTED - fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n"); +#ifdef DCT_SCALING_SUPPORTED + fprintf(stderr, " -scale M/N Scale image by fraction M/N, eg, 1/2\n"); #endif #ifdef TARGA_SUPPORTED fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); #endif fprintf(stderr, "Switches for advanced users:\n"); +#ifdef C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif +#ifdef DCT_SCALING_SUPPORTED + fprintf(stderr, " -block N DCT block size (1..16; default is 8)\n"); +#endif +#if JPEG_LIB_VERSION_MAJOR >= 9 + fprintf(stderr, " -rgb1 Create RGB JPEG file with reversible color transform\n"); + fprintf(stderr, " -bgycc Create big gamut YCC JPEG file\n"); +#endif #ifdef DCT_ISLOW_SUPPORTED fprintf(stderr, " -dct int Use integer DCT method%s\n", (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); @@ -176,6 +188,7 @@ usage (void) fprintf(stderr, " -dct float Use floating-point DCT method%s\n", (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); #endif + fprintf(stderr, " -nosmooth Don't use high-quality downsampling\n"); fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); #ifdef INPUT_SMOOTHING_SUPPORTED fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n"); @@ -184,9 +197,6 @@ usage (void) fprintf(stderr, " -outfile name Specify name for output file\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, "Switches for wizards:\n"); -#ifdef C_ARITH_CODING_SUPPORTED - fprintf(stderr, " -arithmetic Use arithmetic coding\n"); -#endif fprintf(stderr, " -baseline Force baseline quantization tables\n"); fprintf(stderr, " -qtables file Use quantization tables given in file\n"); fprintf(stderr, " -qslots N[,...] Set component quantization tables\n"); @@ -212,22 +222,16 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, { int argn; char * arg; - int quality; /* -quality parameter */ - int q_scale_factor; /* scaling percentage for -qtables */ boolean force_baseline; boolean simple_progressive; + char * qualityarg = NULL; /* saves -quality parm if any */ char * qtablefile = NULL; /* saves -qtables filename if any */ char * qslotsarg = NULL; /* saves -qslots parm if any */ char * samplearg = NULL; /* saves -sample parm if any */ char * scansarg = NULL; /* saves -scans parm if any */ - char * losslsarg = NULL; /* saves -lossless parm if any */ /* Set up default JPEG parameters. */ - /* Note that default -quality level need not, and does not, - * match the default scaling for an explicit -qtables argument. - */ - quality = 75; /* default -quality value */ - q_scale_factor = 100; /* default to no scaling for -qtables */ + force_baseline = FALSE; /* by default, allow 16-bit quantizers */ simple_progressive = FALSE; is_targa = FALSE; @@ -258,10 +262,29 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, exit(EXIT_FAILURE); #endif - } else if (keymatch(arg, "baseline", 1)) { + } else if (keymatch(arg, "baseline", 2)) { /* Force baseline-compatible output (8-bit quantizer values). */ force_baseline = TRUE; + } else if (keymatch(arg, "block", 2)) { + /* Set DCT block size. */ +#if defined DCT_SCALING_SUPPORTED && JPEG_LIB_VERSION_MAJOR >= 8 && \ + (JPEG_LIB_VERSION_MAJOR > 8 || JPEG_LIB_VERSION_MINOR >= 3) + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + if (val < 1 || val > 16) + usage(); + cinfo->block_size = val; +#else + fprintf(stderr, "%s: sorry, block size setting not supported\n", + progname); + exit(EXIT_FAILURE); +#endif + } else if (keymatch(arg, "dct", 2)) { /* Select DCT algorithm. */ if (++argn >= argc) /* advance to next argument */ @@ -291,15 +314,23 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, /* Force a monochrome JPEG file to be generated. */ jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); - } else if (keymatch(arg, "lossless", 1)) { -/* Select simple lossless mode. */ -#ifdef C_LOSSLESS_SUPPORTED - if (++argn >= argc) /* advance to next argument */ - usage(); - losslsarg = argv[argn]; - /* We must postpone execution until num_components is known. */ + } else if (keymatch(arg, "rgb", 3) || keymatch(arg, "rgb1", 4)) { + /* Force an RGB JPEG file to be generated. */ +#if JPEG_LIB_VERSION_MAJOR >= 9 + /* Note: Entropy table assignment in jpeg_set_colorspace depends + * on color_transform. + */ + cinfo->color_transform = arg[3] ? JCT_SUBTRACT_GREEN : JCT_NONE; +#endif + jpeg_set_colorspace(cinfo, JCS_RGB); + + } else if (keymatch(arg, "bgycc", 5)) { + /* Force a big gamut YCC JPEG file to be generated. */ +#if JPEG_LIB_VERSION_MAJOR >= 9 && \ + (JPEG_LIB_VERSION_MAJOR > 9 || JPEG_LIB_VERSION_MINOR >= 1) + jpeg_set_colorspace(cinfo, JCS_BG_YCC); #else - fprintf(stderr, "%s: sorry, lossless output was not compiled\n", + fprintf(stderr, "%s: sorry, BG_YCC colorspace not supported\n", progname); exit(EXIT_FAILURE); #endif @@ -317,6 +348,10 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, lval *= 1000L; cinfo->mem->max_memory_to_use = lval * 1000L; + } else if (keymatch(arg, "nosmooth", 3)) { + /* Suppress fancy downsampling. */ + cinfo->do_fancy_downsampling = FALSE; + } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { /* Enable entropy parm optimization. */ #ifdef ENTROPY_OPT_SUPPORTED @@ -345,13 +380,10 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, #endif } else if (keymatch(arg, "quality", 1)) { - /* Quality factor (quantization table scaling factor). */ + /* Quality ratings (quantization table scaling factors). */ if (++argn >= argc) /* advance to next argument */ usage(); - if (sscanf(argv[argn], "%d", &quality) != 1) - usage(); - /* Change scale factor in case -qtables is present. */ - q_scale_factor = jpeg_quality_scaling(quality); + qualityarg = argv[argn]; } else if (keymatch(arg, "qslots", 2)) { /* Quantization table slot numbers. */ @@ -399,7 +431,15 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, * default sampling factors. */ - } else if (keymatch(arg, "scans", 2)) { + } else if (keymatch(arg, "scale", 4)) { + /* Scale the image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%u/%u", + &cinfo->scale_num, &cinfo->scale_denom) != 2) + usage(); + + } else if (keymatch(arg, "scans", 4)) { /* Set scan script. */ #ifdef C_MULTISCAN_FILES_SUPPORTED if (++argn >= argc) /* advance to next argument */ @@ -439,11 +479,12 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, /* Set quantization tables for selected quality. */ /* Some or all may be overridden if -qtables is present. */ - jpeg_set_quality(cinfo, quality, force_baseline); + if (qualityarg != NULL) /* process -quality if it was present */ + if (! set_quality_ratings(cinfo, qualityarg, force_baseline)) + usage(); if (qtablefile != NULL) /* process -qtables if it was present */ - if (! read_quant_tables(cinfo, qtablefile, - q_scale_factor, force_baseline)) + if (! read_quant_tables(cinfo, qtablefile, force_baseline)) usage(); if (qslotsarg != NULL) /* process -qslots if it was present */ @@ -459,12 +500,6 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, jpeg_simple_progression(cinfo); #endif -#ifdef C_LOSSLESS_SUPPORTED - if (losslsarg != NULL) /* process -lossless if it was present */ - if (! set_simple_lossless(cinfo, losslsarg)) - usage(); -#endif - #ifdef C_MULTISCAN_FILES_SUPPORTED if (scansarg != NULL) /* process -scans if it was present */ if (! read_scan_script(cinfo, scansarg)) diff --git a/uppsrc/plugin/jpg/lib/ckconfig.c b/uppsrc/plugin/jpg/lib/ckconfig.c index 58e9c17f2..fb9429af0 100644 --- a/uppsrc/plugin/jpg/lib/ckconfig.c +++ b/uppsrc/plugin/jpg/lib/ckconfig.c @@ -301,7 +301,7 @@ int main (argc, argv) /* Write out all the info */ fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n"); - fprintf(outfile, "/* see jconfig.doc for explanations */\n\n"); + fprintf(outfile, "/* see jconfig.txt for explanations */\n\n"); #ifdef HAVE_PROTOTYPES fprintf(outfile, "#define HAVE_PROTOTYPES\n"); #else diff --git a/uppsrc/plugin/jpg/lib/djpeg.c b/uppsrc/plugin/jpg/lib/djpeg.c index a63523c5a..2845f306c 100644 --- a/uppsrc/plugin/jpg/lib/djpeg.c +++ b/uppsrc/plugin/jpg/lib/djpeg.c @@ -2,6 +2,7 @@ * djpeg.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2009-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -101,6 +102,7 @@ usage (void) fprintf(stderr, " -colors N Reduce image to no more than N colors\n"); fprintf(stderr, " -fast Fast, low-quality processing\n"); fprintf(stderr, " -grayscale Force grayscale output\n"); + fprintf(stderr, " -rgb Force RGB output\n"); #ifdef IDCT_SCALING_SUPPORTED fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); #endif @@ -263,6 +265,10 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv, /* Force monochrome output. */ cinfo->out_color_space = JCS_GRAYSCALE; + } else if (keymatch(arg, "rgb", 3)) { + /* Force RGB output. */ + cinfo->out_color_space = JCS_RGB; + } else if (keymatch(arg, "map", 3)) { /* Quantize to a color map taken from an input file. */ if (++argn >= argc) /* advance to next argument */ @@ -297,7 +303,7 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv, cinfo->mem->max_memory_to_use = lval * 1000L; } else if (keymatch(arg, "nosmooth", 3)) { - /* Suppress fancy upsampling */ + /* Suppress fancy upsampling. */ cinfo->do_fancy_upsampling = FALSE; } else if (keymatch(arg, "onepass", 3)) { @@ -326,8 +332,8 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv, /* Scale the output image by a fraction M/N. */ if (++argn >= argc) /* advance to next argument */ usage(); - if (sscanf(argv[argn], "%d/%d", - &cinfo->scale_num, &cinfo->scale_denom) != 2) + if (sscanf(argv[argn], "%u/%u", + &cinfo->scale_num, &cinfo->scale_denom) < 1) usage(); } else if (keymatch(arg, "targa", 1)) { diff --git a/uppsrc/plugin/jpg/lib/example.c b/uppsrc/plugin/jpg/lib/example.c index 17b9a3c9e..e21cf1212 100644 --- a/uppsrc/plugin/jpg/lib/example.c +++ b/uppsrc/plugin/jpg/lib/example.c @@ -3,10 +3,10 @@ * * This file illustrates how to use the IJG code as a subroutine library * to read or write JPEG image files. You should look at this code in - * conjunction with the documentation file libjpeg.doc. + * conjunction with the documentation file libjpeg.txt. * * This code will not do anything useful as-is, but it may be helpful as a - * skeleton for constructing routines that call the JPEG library. + * skeleton for constructing routines that call the JPEG library. * * We present these routines in the same coding style used in the JPEG code * (ANSI function definitions, etc); but you are of course free to code your @@ -196,7 +196,7 @@ write_JPEG_file (char * filename, int quality) * files for anything that doesn't fit within the maximum-memory setting. * (Note that temp files are NOT needed if you use the default parameters.) * On some systems you may need to set up a signal handler to ensure that - * temporary files are deleted if the program is interrupted. See libjpeg.doc. + * temporary files are deleted if the program is interrupted. See libjpeg.txt. * * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG * files to be compatible with everyone else's. If you cannot readily read @@ -335,7 +335,7 @@ read_JPEG_file (char * filename) /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. - * See libjpeg.doc for more info. + * See libjpeg.txt for more info. */ /* Step 4: set parameters for decompression */ @@ -356,7 +356,7 @@ read_JPEG_file (char * filename) * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. - */ + */ /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ @@ -413,14 +413,14 @@ read_JPEG_file (char * filename) * In the above code, we ignored the return value of jpeg_read_scanlines, * which is the number of scanlines actually read. We could get away with * this because we asked for only one line at a time and we weren't using - * a suspending data source. See libjpeg.doc for more info. + * a suspending data source. See libjpeg.txt for more info. * * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress(); * we should have done it beforehand to ensure that the space would be * counted against the JPEG max_memory setting. In some systems the above * code would risk an out-of-memory error. However, in general we don't * know the output image dimensions before jpeg_start_decompress(), unless we - * call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this. + * call jpeg_calc_output_dimensions(). See libjpeg.txt for more about this. * * Scanlines are returned in the same order as they appear in the JPEG file, * which is standardly top-to-bottom. If you must emit data bottom-to-top, @@ -429,5 +429,5 @@ read_JPEG_file (char * filename) * * As with compression, some operating modes may require temporary files. * On some systems you may need to set up a signal handler to ensure that - * temporary files are deleted if the program is interrupted. See libjpeg.doc. + * temporary files are deleted if the program is interrupted. See libjpeg.txt. */ diff --git a/uppsrc/plugin/jpg/lib/jaricom.c b/uppsrc/plugin/jpg/lib/jaricom.c new file mode 100644 index 000000000..50ad879f5 --- /dev/null +++ b/uppsrc/plugin/jpg/lib/jaricom.c @@ -0,0 +1,153 @@ +/* + * jaricom.c + * + * Developed 1997-2011 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains probability estimation tables for common use in + * arithmetic entropy encoding and decoding routines. + * + * This data represents Table D.3 in the JPEG spec (D.2 in the draft), + * ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81, and Table 24 + * in the JBIG spec, ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +/* The following #define specifies the packing of the four components + * into the compact INT32 representation. + * Note that this formula must match the actual arithmetic encoder + * and decoder implementation. The implementation has to be changed + * if this formula is changed. + * The current organization is leaned on Markus Kuhn's JBIG + * implementation (jbig_tab.c). + */ + +#define V(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) + +const INT32 jpeg_aritab[113+1] = { +/* + * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS + */ + V( 0, 0x5a1d, 1, 1, 1 ), + V( 1, 0x2586, 14, 2, 0 ), + V( 2, 0x1114, 16, 3, 0 ), + V( 3, 0x080b, 18, 4, 0 ), + V( 4, 0x03d8, 20, 5, 0 ), + V( 5, 0x01da, 23, 6, 0 ), + V( 6, 0x00e5, 25, 7, 0 ), + V( 7, 0x006f, 28, 8, 0 ), + V( 8, 0x0036, 30, 9, 0 ), + V( 9, 0x001a, 33, 10, 0 ), + V( 10, 0x000d, 35, 11, 0 ), + V( 11, 0x0006, 9, 12, 0 ), + V( 12, 0x0003, 10, 13, 0 ), + V( 13, 0x0001, 12, 13, 0 ), + V( 14, 0x5a7f, 15, 15, 1 ), + V( 15, 0x3f25, 36, 16, 0 ), + V( 16, 0x2cf2, 38, 17, 0 ), + V( 17, 0x207c, 39, 18, 0 ), + V( 18, 0x17b9, 40, 19, 0 ), + V( 19, 0x1182, 42, 20, 0 ), + V( 20, 0x0cef, 43, 21, 0 ), + V( 21, 0x09a1, 45, 22, 0 ), + V( 22, 0x072f, 46, 23, 0 ), + V( 23, 0x055c, 48, 24, 0 ), + V( 24, 0x0406, 49, 25, 0 ), + V( 25, 0x0303, 51, 26, 0 ), + V( 26, 0x0240, 52, 27, 0 ), + V( 27, 0x01b1, 54, 28, 0 ), + V( 28, 0x0144, 56, 29, 0 ), + V( 29, 0x00f5, 57, 30, 0 ), + V( 30, 0x00b7, 59, 31, 0 ), + V( 31, 0x008a, 60, 32, 0 ), + V( 32, 0x0068, 62, 33, 0 ), + V( 33, 0x004e, 63, 34, 0 ), + V( 34, 0x003b, 32, 35, 0 ), + V( 35, 0x002c, 33, 9, 0 ), + V( 36, 0x5ae1, 37, 37, 1 ), + V( 37, 0x484c, 64, 38, 0 ), + V( 38, 0x3a0d, 65, 39, 0 ), + V( 39, 0x2ef1, 67, 40, 0 ), + V( 40, 0x261f, 68, 41, 0 ), + V( 41, 0x1f33, 69, 42, 0 ), + V( 42, 0x19a8, 70, 43, 0 ), + V( 43, 0x1518, 72, 44, 0 ), + V( 44, 0x1177, 73, 45, 0 ), + V( 45, 0x0e74, 74, 46, 0 ), + V( 46, 0x0bfb, 75, 47, 0 ), + V( 47, 0x09f8, 77, 48, 0 ), + V( 48, 0x0861, 78, 49, 0 ), + V( 49, 0x0706, 79, 50, 0 ), + V( 50, 0x05cd, 48, 51, 0 ), + V( 51, 0x04de, 50, 52, 0 ), + V( 52, 0x040f, 50, 53, 0 ), + V( 53, 0x0363, 51, 54, 0 ), + V( 54, 0x02d4, 52, 55, 0 ), + V( 55, 0x025c, 53, 56, 0 ), + V( 56, 0x01f8, 54, 57, 0 ), + V( 57, 0x01a4, 55, 58, 0 ), + V( 58, 0x0160, 56, 59, 0 ), + V( 59, 0x0125, 57, 60, 0 ), + V( 60, 0x00f6, 58, 61, 0 ), + V( 61, 0x00cb, 59, 62, 0 ), + V( 62, 0x00ab, 61, 63, 0 ), + V( 63, 0x008f, 61, 32, 0 ), + V( 64, 0x5b12, 65, 65, 1 ), + V( 65, 0x4d04, 80, 66, 0 ), + V( 66, 0x412c, 81, 67, 0 ), + V( 67, 0x37d8, 82, 68, 0 ), + V( 68, 0x2fe8, 83, 69, 0 ), + V( 69, 0x293c, 84, 70, 0 ), + V( 70, 0x2379, 86, 71, 0 ), + V( 71, 0x1edf, 87, 72, 0 ), + V( 72, 0x1aa9, 87, 73, 0 ), + V( 73, 0x174e, 72, 74, 0 ), + V( 74, 0x1424, 72, 75, 0 ), + V( 75, 0x119c, 74, 76, 0 ), + V( 76, 0x0f6b, 74, 77, 0 ), + V( 77, 0x0d51, 75, 78, 0 ), + V( 78, 0x0bb6, 77, 79, 0 ), + V( 79, 0x0a40, 77, 48, 0 ), + V( 80, 0x5832, 80, 81, 1 ), + V( 81, 0x4d1c, 88, 82, 0 ), + V( 82, 0x438e, 89, 83, 0 ), + V( 83, 0x3bdd, 90, 84, 0 ), + V( 84, 0x34ee, 91, 85, 0 ), + V( 85, 0x2eae, 92, 86, 0 ), + V( 86, 0x299a, 93, 87, 0 ), + V( 87, 0x2516, 86, 71, 0 ), + V( 88, 0x5570, 88, 89, 1 ), + V( 89, 0x4ca9, 95, 90, 0 ), + V( 90, 0x44d9, 96, 91, 0 ), + V( 91, 0x3e22, 97, 92, 0 ), + V( 92, 0x3824, 99, 93, 0 ), + V( 93, 0x32b4, 99, 94, 0 ), + V( 94, 0x2e17, 93, 86, 0 ), + V( 95, 0x56a8, 95, 96, 1 ), + V( 96, 0x4f46, 101, 97, 0 ), + V( 97, 0x47e5, 102, 98, 0 ), + V( 98, 0x41cf, 103, 99, 0 ), + V( 99, 0x3c3d, 104, 100, 0 ), + V( 100, 0x375e, 99, 93, 0 ), + V( 101, 0x5231, 105, 102, 0 ), + V( 102, 0x4c0f, 106, 103, 0 ), + V( 103, 0x4639, 107, 104, 0 ), + V( 104, 0x415e, 103, 99, 0 ), + V( 105, 0x5627, 105, 106, 1 ), + V( 106, 0x50e7, 108, 107, 0 ), + V( 107, 0x4b85, 109, 103, 0 ), + V( 108, 0x5597, 110, 109, 0 ), + V( 109, 0x504f, 111, 107, 0 ), + V( 110, 0x5a10, 110, 111, 1 ), + V( 111, 0x5522, 112, 109, 0 ), + V( 112, 0x59eb, 112, 111, 1 ), +/* + * This last entry is used for fixed probability estimate of 0.5 + * as suggested in Section 10.3 Table 5 of ITU-T Rec. T.851. + */ + V( 113, 0x5a1d, 113, 113, 0 ) +}; diff --git a/uppsrc/plugin/jpg/lib/jcapimin.c b/uppsrc/plugin/jpg/lib/jcapimin.c index 0533c0d55..3382d9155 100644 --- a/uppsrc/plugin/jpg/lib/jcapimin.c +++ b/uppsrc/plugin/jpg/lib/jcapimin.c @@ -2,6 +2,7 @@ * jcapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2003-2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -36,7 +37,7 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) if (version != JPEG_LIB_VERSION) ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_compress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); /* For debugging purposes, we zero the whole master structure. @@ -63,14 +64,21 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) cinfo->comp_info = NULL; - for (i = 0; i < NUM_QUANT_TBLS; i++) + for (i = 0; i < NUM_QUANT_TBLS; i++) { cinfo->quant_tbl_ptrs[i] = NULL; + cinfo->q_scale_factor[i] = 100; + } for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } + /* Must do it here for emit_dqt in case jpeg_write_tables is used */ + cinfo->block_size = DCTSIZE; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + cinfo->script_space = NULL; cinfo->input_gamma = 1.0; /* in case application forgets */ @@ -168,7 +176,7 @@ jpeg_finish_compress (j_compress_ptr cinfo) /* We bypass the main controller and invoke coef controller directly; * all work is being done from the coefficient buffer. */ - if (! (*cinfo->codec->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } (*cinfo->master->finish_pass) (cinfo); diff --git a/uppsrc/plugin/jpg/lib/jcapistd.c b/uppsrc/plugin/jpg/lib/jcapistd.c index fbb86ba41..8892bfaac 100644 --- a/uppsrc/plugin/jpg/lib/jcapistd.c +++ b/uppsrc/plugin/jpg/lib/jcapistd.c @@ -2,6 +2,7 @@ * jcapistd.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -145,12 +146,12 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, (*cinfo->master->pass_startup) (cinfo); /* Verify that at least one iMCU row has been passed. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->data_unit; + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; if (num_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Directly compress the row. */ - if (! (*cinfo->codec->compress_data) (cinfo, data)) { + if (! (*cinfo->coef->compress_data) (cinfo, data)) { /* If compressor did not consume the whole row, suspend processing. */ return 0; } diff --git a/uppsrc/plugin/jpg/lib/jcarith.c b/uppsrc/plugin/jpg/lib/jcarith.c new file mode 100644 index 000000000..3bc0a5b8d --- /dev/null +++ b/uppsrc/plugin/jpg/lib/jcarith.c @@ -0,0 +1,944 @@ +/* + * jcarith.c + * + * Developed 1997-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains portable arithmetic entropy encoding routines for JPEG + * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). + * + * Both sequential and progressive modes are supported in this single module. + * + * Suspension is not currently supported in this module. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Expanded entropy encoder object for arithmetic encoding. */ + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + INT32 c; /* C register, base of coding interval, layout as in sec. D.1.3 */ + INT32 a; /* A register, normalized size of coding interval */ + INT32 sc; /* counter for stacked 0xFF values which might overflow */ + INT32 zc; /* counter for pending 0x00 output values which might * + * be discarded at the end ("Pacman" termination) */ + int ct; /* bit shift counter, determines when next byte will be written */ + int buffer; /* buffer for most recent output byte != 0xFF */ + + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to statistics areas (these workspaces have image lifespan) */ + unsigned char * dc_stats[NUM_ARITH_TBLS]; + unsigned char * ac_stats[NUM_ARITH_TBLS]; + + /* Statistics bin for coding with fixed probability 0.5 */ + unsigned char fixed_bin[4]; +} arith_entropy_encoder; + +typedef arith_entropy_encoder * arith_entropy_ptr; + +/* The following two definitions specify the allocation chunk size + * for the statistics area. + * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least + * 49 statistics bins for DC, and 245 statistics bins for AC coding. + * + * We use a compact representation with 1 byte per statistics bin, + * thus the numbers directly represent byte sizes. + * This 1 byte per statistics bin contains the meaning of the MPS + * (more probable symbol) in the highest bit (mask 0x80), and the + * index into the probability estimation state machine table + * in the lower bits (mask 0x7F). + */ + +#define DC_STAT_BINS 64 +#define AC_STAT_BINS 256 + +/* NOTE: Uncomment the following #define if you want to use the + * given formula for calculating the AC conditioning parameter Kx + * for spectral selection progressive coding in section G.1.3.2 + * of the spec (Kx = Kmin + SRL (8 + Se - Kmin) 4). + * Although the spec and P&M authors claim that this "has proven + * to give good results for 8 bit precision samples", I'm not + * convinced yet that this is really beneficial. + * Early tests gave only very marginal compression enhancements + * (a few - around 5 or so - bytes even for very large files), + * which would turn out rather negative if we'd suppress the + * DAC (Define Arithmetic Conditioning) marker segments for + * the default parameters in the future. + * Note that currently the marker writing module emits 12-byte + * DAC segments for a full-component scan in a color image. + * This is not worth worrying about IMHO. However, since the + * spec defines the default values to be used if the tables + * are omitted (unlike Huffman tables, which are required + * anyway), one might optimize this behaviour in the future, + * and then it would be disadvantageous to use custom tables if + * they don't provide sufficient gain to exceed the DAC size. + * + * On the other hand, I'd consider it as a reasonable result + * that the conditioning has no significant influence on the + * compression performance. This means that the basic + * statistical model is already rather stable. + * + * Thus, at the moment, we use the default conditioning values + * anyway, and do not use the custom formula. + * +#define CALCULATE_SPECTRAL_CONDITIONING + */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +LOCAL(void) +emit_byte (int val, j_compress_ptr cinfo) +/* Write next output byte; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *dest->next_output_byte++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); +} + + +/* + * Finish up at the end of an arithmetic-compressed scan. + */ + +METHODDEF(void) +finish_pass (j_compress_ptr cinfo) +{ + arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + INT32 temp; + + /* Section D.1.8: Termination of encoding */ + + /* Find the e->c in the coding interval with the largest + * number of trailing zero bits */ + if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c) + e->c = temp + 0x8000L; + else + e->c = temp; + /* Send remaining bytes to output */ + e->c <<= e->ct; + if (e->c & 0xF8000000L) { + /* One final overflow has to be handled */ + if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer + 1, cinfo); + if (e->buffer + 1 == 0xFF) + emit_byte(0x00, cinfo); + } + e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ + e->sc = 0; + } else { + if (e->buffer == 0) + ++e->zc; + else if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer, cinfo); + } + if (e->sc) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + do { + emit_byte(0xFF, cinfo); + emit_byte(0x00, cinfo); + } while (--e->sc); + } + } + /* Output final bytes only if they are not 0x00 */ + if (e->c & 0x7FFF800L) { + if (e->zc) /* output final pending zero bytes */ + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte((e->c >> 19) & 0xFF, cinfo); + if (((e->c >> 19) & 0xFF) == 0xFF) + emit_byte(0x00, cinfo); + if (e->c & 0x7F800L) { + emit_byte((e->c >> 11) & 0xFF, cinfo); + if (((e->c >> 11) & 0xFF) == 0xFF) + emit_byte(0x00, cinfo); + } + } +} + + +/* + * The core arithmetic encoding routine (common in JPEG and JBIG). + * This needs to go as fast as possible. + * Machine-dependent optimization facilities + * are not utilized in this portable implementation. + * However, this code should be fairly efficient and + * may be a good base for further optimizations anyway. + * + * Parameter 'val' to be encoded may be 0 or 1 (binary decision). + * + * Note: I've added full "Pacman" termination support to the + * byte output routines, which is equivalent to the optional + * Discard_final_zeros procedure (Figure D.15) in the spec. + * Thus, we always produce the shortest possible output + * stream compliant to the spec (no trailing zero bytes, + * except for FF stuffing). + * + * I've also introduced a new scheme for accessing + * the probability estimation state machine table, + * derived from Markus Kuhn's JBIG implementation. + */ + +LOCAL(void) +arith_encode (j_compress_ptr cinfo, unsigned char *st, int val) +{ + register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + register unsigned char nl, nm; + register INT32 qe, temp; + register int sv; + + /* Fetch values from our compact representation of Table D.3(D.2): + * Qe values and probability estimation state machine + */ + sv = *st; + qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ + nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ + nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ + + /* Encode & estimation procedures per sections D.1.4 & D.1.5 */ + e->a -= qe; + if (val != (sv >> 7)) { + /* Encode the less probable symbol */ + if (e->a >= qe) { + /* If the interval size (qe) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency, otherwise code the LPS + * as usual: */ + e->c += e->a; + e->a = qe; + } + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + } else { + /* Encode the more probable symbol */ + if (e->a >= 0x8000L) + return; /* A >= 0x8000 -> ready, no renormalization required */ + if (e->a < qe) { + /* If the interval size (qe) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency: */ + e->c += e->a; + e->a = qe; + } + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } + + /* Renormalization & data output per section D.1.6 */ + do { + e->a <<= 1; + e->c <<= 1; + if (--e->ct == 0) { + /* Another byte is ready for output */ + temp = e->c >> 19; + if (temp > 0xFF) { + /* Handle overflow over all stacked 0xFF bytes */ + if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer + 1, cinfo); + if (e->buffer + 1 == 0xFF) + emit_byte(0x00, cinfo); + } + e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ + e->sc = 0; + /* Note: The 3 spacer bits in the C register guarantee + * that the new buffer byte can't be 0xFF here + * (see page 160 in the P&M JPEG book). */ + e->buffer = temp & 0xFF; /* new output byte, might overflow later */ + } else if (temp == 0xFF) { + ++e->sc; /* stack 0xFF byte (which might overflow later) */ + } else { + /* Output all stacked 0xFF bytes, they will not overflow any more */ + if (e->buffer == 0) + ++e->zc; + else if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer, cinfo); + } + if (e->sc) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + do { + emit_byte(0xFF, cinfo); + emit_byte(0x00, cinfo); + } while (--e->sc); + } + e->buffer = temp & 0xFF; /* new output byte (can still overflow) */ + } + e->c &= 0x7FFFFL; + e->ct += 8; + } + } while (e->a < 0x8000L); +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (j_compress_ptr cinfo, int restart_num) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci; + jpeg_component_info * compptr; + + finish_pass(cinfo); + + emit_byte(0xFF, cinfo); + emit_byte(JPEG_RST0 + restart_num, cinfo); + + /* Re-initialize statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); + /* Reset DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); + } + } + + /* Reset arithmetic encoding variables */ + entropy->c = 0; + entropy->a = 0x10000L; + entropy->sc = 0; + entropy->zc = 0; + entropy->ct = 11; + entropy->buffer = -1; /* empty */ +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + unsigned char *st; + int blkn, ci, tbl; + int v, v2, m; + ISHIFT_TEMPS + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + m = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al); + + /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.4: Encode_DC_DIFF */ + if ((v = m - entropy->last_dc_val[ci]) == 0) { + arith_encode(cinfo, st, 0); + entropy->dc_context[ci] = 0; /* zero diff category */ + } else { + entropy->last_dc_val[ci] = m; + arith_encode(cinfo, st, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ + st += 2; /* Table F.4: SP = S0 + 2 */ + entropy->dc_context[ci] = 4; /* small positive diff category */ + } else { + v = -v; + arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ + st += 3; /* Table F.4: SN = S0 + 3 */ + entropy->dc_context[ci] = 8; /* small negative diff category */ + } + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + arith_encode(cinfo, st, 0); + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] += 8; /* large diff category */ + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + const int * natural_order; + JBLOCKROW block; + unsigned char *st; + int tbl, k, ke; + int v, v2, m; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ + + /* Establish EOB (end-of-block) index */ + ke = cinfo->Se; + do { + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if ((v = (*block)[natural_order[ke]]) >= 0) { + if (v >>= cinfo->Al) break; + } else { + v = -v; + if (v >>= cinfo->Al) break; + } + } while (--ke); + + /* Figure F.5: Encode_AC_Coefficients */ + for (k = cinfo->Ss - 1; k < ke;) { + st = entropy->ac_stats[tbl] + 3 * k; + arith_encode(cinfo, st, 0); /* EOB decision */ + for (;;) { + if ((v = (*block)[natural_order[++k]]) >= 0) { + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + break; + } + } else { + v = -v; + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 1); + break; + } + } + arith_encode(cinfo, st + 1, 0); + st += 3; + } + st += 2; + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + if (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + } + arith_encode(cinfo, st, 0); + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + /* Encode EOB decision only if k < cinfo->Se */ + if (k < cinfo->Se) { + st = entropy->ac_stats[tbl] + 3 * k; + arith_encode(cinfo, st, 1); + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, + * although the spec is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + unsigned char *st; + int Al, blkn; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + st = entropy->fixed_bin; /* use fixed probability estimation */ + Al = cinfo->Al; + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* We simply emit the Al'th bit of the DC coefficient value. */ + arith_encode(cinfo, st, (MCU_data[blkn][0][0] >> Al) & 1); + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + const int * natural_order; + JBLOCKROW block; + unsigned char *st; + int tbl, k, ke, kex; + int v; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Section G.1.3.3: Encoding of AC coefficients */ + + /* Establish EOB (end-of-block) index */ + ke = cinfo->Se; + do { + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if ((v = (*block)[natural_order[ke]]) >= 0) { + if (v >>= cinfo->Al) break; + } else { + v = -v; + if (v >>= cinfo->Al) break; + } + } while (--ke); + + /* Establish EOBx (previous stage end-of-block) index */ + for (kex = ke; kex > 0; kex--) + if ((v = (*block)[natural_order[kex]]) >= 0) { + if (v >>= cinfo->Ah) break; + } else { + v = -v; + if (v >>= cinfo->Ah) break; + } + + /* Figure G.10: Encode_AC_Coefficients_SA */ + for (k = cinfo->Ss - 1; k < ke;) { + st = entropy->ac_stats[tbl] + 3 * k; + if (k >= kex) + arith_encode(cinfo, st, 0); /* EOB decision */ + for (;;) { + if ((v = (*block)[natural_order[++k]]) >= 0) { + if (v >>= cinfo->Al) { + if (v >> 1) /* previously nonzero coef */ + arith_encode(cinfo, st + 2, (v & 1)); + else { /* newly nonzero coef */ + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + } + break; + } + } else { + v = -v; + if (v >>= cinfo->Al) { + if (v >> 1) /* previously nonzero coef */ + arith_encode(cinfo, st + 2, (v & 1)); + else { /* newly nonzero coef */ + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 1); + } + break; + } + } + arith_encode(cinfo, st + 1, 0); + st += 3; + } + } + /* Encode EOB decision only if k < cinfo->Se */ + if (k < cinfo->Se) { + st = entropy->ac_stats[tbl] + 3 * k; + arith_encode(cinfo, st, 1); + } + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of arithmetic-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + const int * natural_order; + JBLOCKROW block; + unsigned char *st; + int tbl, k, ke; + int v, v2, m; + int blkn, ci; + jpeg_component_info * compptr; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ + + tbl = compptr->dc_tbl_no; + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.4: Encode_DC_DIFF */ + if ((v = (*block)[0] - entropy->last_dc_val[ci]) == 0) { + arith_encode(cinfo, st, 0); + entropy->dc_context[ci] = 0; /* zero diff category */ + } else { + entropy->last_dc_val[ci] = (*block)[0]; + arith_encode(cinfo, st, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ + st += 2; /* Table F.4: SP = S0 + 2 */ + entropy->dc_context[ci] = 4; /* small positive diff category */ + } else { + v = -v; + arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ + st += 3; /* Table F.4: SN = S0 + 3 */ + entropy->dc_context[ci] = 8; /* small negative diff category */ + } + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + arith_encode(cinfo, st, 0); + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] += 8; /* large diff category */ + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + + /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ + + if ((ke = cinfo->lim_Se) == 0) continue; + tbl = compptr->ac_tbl_no; + + /* Establish EOB (end-of-block) index */ + do { + if ((*block)[natural_order[ke]]) break; + } while (--ke); + + /* Figure F.5: Encode_AC_Coefficients */ + for (k = 0; k < ke;) { + st = entropy->ac_stats[tbl] + 3 * k; + arith_encode(cinfo, st, 0); /* EOB decision */ + while ((v = (*block)[natural_order[++k]]) == 0) { + arith_encode(cinfo, st + 1, 0); + st += 3; + } + arith_encode(cinfo, st + 1, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, entropy->fixed_bin, 0); + } else { + v = -v; + arith_encode(cinfo, entropy->fixed_bin, 1); + } + st += 2; + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + if (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + } + arith_encode(cinfo, st, 0); + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + /* Encode EOB decision only if k < cinfo->lim_Se */ + if (k < cinfo->lim_Se) { + st = entropy->ac_stats[tbl] + 3 * k; + arith_encode(cinfo, st, 1); + } + } + + return TRUE; +} + + +/* + * Initialize for an arithmetic-compressed scan. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, boolean gather_statistics) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (gather_statistics) + /* Make sure to avoid that in the master control logic! + * We are fully adaptive here and need no extra + * statistics gathering pass! + */ + ERREXIT(cinfo, JERR_NOT_COMPILED); + + /* We assume jcmaster.c already validated the progressive scan parameters. */ + + /* Select execution routines */ + if (cinfo->progressive_mode) { + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else + entropy->pub.encode_mcu = encode_mcu_AC_refine; + } + } else + entropy->pub.encode_mcu = encode_mcu; + + /* Allocate & initialize requested statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->dc_stats[tbl] == NULL) + entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); + MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->ac_stats[tbl] == NULL) + entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); + MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); +#ifdef CALCULATE_SPECTRAL_CONDITIONING + if (cinfo->progressive_mode) + /* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */ + cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4); +#endif + } + } + + /* Initialize arithmetic encoding variables */ + entropy->c = 0; + entropy->a = 0x10000L; + entropy->sc = 0; + entropy->zc = 0; + entropy->ct = 11; + entropy->buffer = -1; /* empty */ + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Module initialization routine for arithmetic entropy encoding. + */ + +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo) +{ + arith_entropy_ptr entropy; + int i; + + entropy = (arith_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(arith_entropy_encoder)); + cinfo->entropy = &entropy->pub; + entropy->pub.start_pass = start_pass; + entropy->pub.finish_pass = finish_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + entropy->dc_stats[i] = NULL; + entropy->ac_stats[i] = NULL; + } + + /* Initialize index for fixed probability estimation */ + entropy->fixed_bin[0] = 113; +} diff --git a/uppsrc/plugin/jpg/lib/jccoefct.c b/uppsrc/plugin/jpg/lib/jccoefct.c index dab0714d3..b64b46e75 100644 --- a/uppsrc/plugin/jpg/lib/jccoefct.c +++ b/uppsrc/plugin/jpg/lib/jccoefct.c @@ -1,7 +1,8 @@ /* * jccoefct.c * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2003-2011 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -13,7 +14,6 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy codec */ /* We use a full-image coefficient buffer when doing Huffman optimization, @@ -33,6 +33,8 @@ /* Private buffer controller object */ typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + JDIMENSION iMCU_row_num; /* iMCU row # within image */ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ @@ -40,20 +42,20 @@ typedef struct { /* For single-pass compression, it's sufficient to buffer just one MCU * (although this may prove a bit slow in practice). We allocate a - * workspace of C_MAX_DATA_UNITS_IN_MCU coefficient blocks, and reuse it for - * each MCU constructed and sent. (On 80x86, the workspace is FAR even - * though it's not really very big; this is to keep the module interfaces - * unchanged when a large coefficient buffer is necessary.) + * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each + * MCU constructed and sent. (On 80x86, the workspace is FAR even though + * it's not really very big; this is to keep the module interfaces unchanged + * when a large coefficient buffer is necessary.) * In multi-pass modes, this array points to the current MCU's blocks * within the virtual arrays. */ - JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU]; + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; /* In multi-pass modes, we need a virtual block array for each component. */ jvirt_barray_ptr whole_image[MAX_COMPONENTS]; -} c_coef_controller; +} my_coef_controller; -typedef c_coef_controller * c_coef_ptr; +typedef my_coef_controller * my_coef_ptr; /* Forward declarations */ @@ -71,8 +73,7 @@ LOCAL(void) start_iMCU_row (j_compress_ptr cinfo) /* Reset within-iMCU-row counters for a new row */ { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. @@ -99,8 +100,7 @@ start_iMCU_row (j_compress_ptr cinfo) METHODDEF(void) start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; coef->iMCU_row_num = 0; start_iMCU_row(cinfo); @@ -109,18 +109,18 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) case JBUF_PASS_THRU: if (coef->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - lossyc->pub.compress_data = compress_data; + coef->pub.compress_data = compress_data; break; #ifdef FULL_COEF_BUFFER_SUPPORTED case JBUF_SAVE_AND_PASS: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - lossyc->pub.compress_data = compress_first_pass; + coef->pub.compress_data = compress_first_pass; break; case JBUF_CRANK_DEST: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - lossyc->pub.compress_data = compress_output; + coef->pub.compress_data = compress_output; break; #endif default: @@ -143,14 +143,14 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) METHODDEF(boolean) compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, bi, ci, yindex, yoffset, blockcnt; JDIMENSION ypos, xpos; jpeg_component_info *compptr; + forward_DCT_ptr forward_DCT; /* Loop to write as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; @@ -169,41 +169,43 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; + forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index]; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; xpos = MCU_col_num * compptr->MCU_sample_width; - ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ + ypos = yoffset * compptr->DCT_v_scaled_size; + /* ypos == (yoffset+yindex) * DCTSIZE */ for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset+yindex < compptr->last_row_height) { - (*lossyc->fdct_forward_DCT) (cinfo, compptr, - input_buf[compptr->component_index], - coef->MCU_buffer[blkn], - ypos, xpos, (JDIMENSION) blockcnt); + (*forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); if (blockcnt < compptr->MCU_width) { /* Create some dummy blocks at the right edge of the image. */ - jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], - (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + FMEMZERO((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); for (bi = blockcnt; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; } } } else { /* Create a row of dummy blocks at the bottom of the image. */ - jzero_far((void FAR *) coef->MCU_buffer[blkn], - compptr->MCU_width * SIZEOF(JBLOCK)); + FMEMZERO((void FAR *) coef->MCU_buffer[blkn], + compptr->MCU_width * SIZEOF(JBLOCK)); for (bi = 0; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; } } blkn += compptr->MCU_width; - ypos += DCTSIZE; + ypos += compptr->DCT_v_scaled_size; } } /* Try to write the MCU. In event of a suspension failure, we will * re-DCT the MCU on restart (a bit inefficient, could be fixed...) */ - if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) { + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; @@ -246,8 +248,7 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) METHODDEF(boolean) compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION blocks_across, MCUs_across, MCUindex; int bi, ci, h_samp_factor, block_row, block_rows, ndummy; @@ -255,6 +256,7 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) jpeg_component_info *compptr; JBLOCKARRAY buffer; JBLOCKROW thisblockrow, lastblockrow; + forward_DCT_ptr forward_DCT; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -268,28 +270,28 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here, since may not be set! */ - block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor); + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } - blocks_across = compptr->width_in_data_units; + blocks_across = compptr->width_in_blocks; h_samp_factor = compptr->h_samp_factor; /* Count number of dummy blocks to be added at the right margin. */ ndummy = (int) (blocks_across % h_samp_factor); if (ndummy > 0) ndummy = h_samp_factor - ndummy; + forward_DCT = cinfo->fdct->forward_DCT[ci]; /* Perform DCT for all non-dummy blocks in this iMCU row. Each call * on forward_DCT processes a complete horizontal row of DCT blocks. */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; - (*lossyc->fdct_forward_DCT) (cinfo, compptr, - input_buf[ci], thisblockrow, - (JDIMENSION) (block_row * DCTSIZE), - (JDIMENSION) 0, blocks_across); + (*forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * compptr->DCT_v_scaled_size), + (JDIMENSION) 0, blocks_across); if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ - jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); + FMEMZERO((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); lastDC = thisblockrow[-1][0]; for (bi = 0; bi < ndummy; bi++) { thisblockrow[bi][0] = lastDC; @@ -308,8 +310,8 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) block_row++) { thisblockrow = buffer[block_row]; lastblockrow = buffer[block_row-1]; - jzero_far((void FAR *) thisblockrow, - (size_t) (blocks_across * SIZEOF(JBLOCK))); + FMEMZERO((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { lastDC = lastblockrow[h_samp_factor-1][0]; for (bi = 0; bi < h_samp_factor; bi++) { @@ -343,8 +345,7 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) METHODDEF(boolean) compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int blkn, ci, xindex, yindex, yoffset; JDIMENSION start_col; @@ -382,7 +383,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) } } /* Try to write the MCU. */ - if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) { + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; @@ -408,14 +409,13 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) GLOBAL(void) jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef; + my_coef_ptr coef; - coef = (c_coef_ptr) + coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(c_coef_controller)); - lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; - lossyc->coef_start_pass = start_pass_coef; + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; /* Create the coefficient buffer. */ if (need_full_buffer) { @@ -429,9 +429,9 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) ci++, compptr++) { coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); } @@ -445,8 +445,8 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->whole_image[0] = NULL; /* flag for no virtual arrays */ diff --git a/uppsrc/plugin/jpg/lib/jccolor.c b/uppsrc/plugin/jpg/lib/jccolor.c index 266372454..aac5802e9 100644 --- a/uppsrc/plugin/jpg/lib/jccolor.c +++ b/uppsrc/plugin/jpg/lib/jccolor.c @@ -2,6 +2,7 @@ * jccolor.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2011-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -28,13 +29,25 @@ typedef my_color_converter * my_cconvert_ptr; /**************** RGB -> YCbCr conversion: most common case **************/ /* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B - * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE - * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011), + * previously known as Recommendation CCIR 601-1, except that Cb and Cr + * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999. + * sYCC (standard luma-chroma-chroma color space with extended gamut) + * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F. + * bg-sRGB and bg-sYCC (big gamut standard color spaces) + * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G. + * Note that the derived conversion coefficients given in some of these + * documents are imprecise. The general conversion equations are + * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B + * Cb = 0.5 * (B - Y) / (1 - Kb) + * Cr = 0.5 * (R - Y) / (1 - Kr) + * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993 + * from the 1953 FCC NTSC primaries and CIE Illuminant C), + * the conversion equations to be implemented are therefore + * Y = 0.299 * R + 0.587 * G + 0.114 * B + * Cb = -0.168735892 * R - 0.331264108 * G + 0.5 * B + CENTERJSAMPLE + * Cr = 0.5 * R - 0.418687589 * G - 0.081312411 * B + CENTERJSAMPLE * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) @@ -48,9 +61,9 @@ typedef my_color_converter * my_cconvert_ptr; * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times R,G,B for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. + * for 9-bit to 12-bit samples it is still acceptable. It's not very + * reasonable for 16-bit samples, but if you want lossless storage you + * shouldn't be changing colorspace anyway. * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included * in the tables to save adding them separately in the inner loop. */ @@ -95,21 +108,21 @@ rgb_ycc_start (j_compress_ptr cinfo) (TABLE_SIZE * SIZEOF(INT32))); for (i = 0; i <= MAXJSAMPLE; i++) { - rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; - rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; - rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; - rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; - rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.299) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.587) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.168735892)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.331264108)) * i; /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. * This ensures that the maximum output will round to MAXJSAMPLE * not MAXJSAMPLE+1, and thus that we don't have to range-limit. */ - rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.5) * i + CBCR_OFFSET + ONE_HALF-1; /* B=>Cb and R=>Cr tables are the same - rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.5) * i + CBCR_OFFSET + ONE_HALF-1; */ - rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; - rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.418687589)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.081312411)) * i; } } @@ -132,8 +145,8 @@ rgb_ycc_convert (j_compress_ptr cinfo, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; + register int r, g, b; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; @@ -149,7 +162,6 @@ rgb_ycc_convert (j_compress_ptr cinfo, r = GETJSAMPLE(inptr[RGB_RED]); g = GETJSAMPLE(inptr[RGB_GREEN]); b = GETJSAMPLE(inptr[RGB_BLUE]); - inptr += RGB_PIXELSIZE; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't @@ -167,6 +179,7 @@ rgb_ycc_convert (j_compress_ptr cinfo, outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); + inptr += RGB_PIXELSIZE; } } } @@ -188,8 +201,8 @@ rgb_gray_convert (j_compress_ptr cinfo, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; + register int r, g, b; register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; @@ -197,17 +210,16 @@ rgb_gray_convert (j_compress_ptr cinfo, while (--num_rows >= 0) { inptr = *input_buf++; - outptr = output_buf[0][output_row]; - output_row++; + outptr = output_buf[0][output_row++]; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr[RGB_RED]); g = GETJSAMPLE(inptr[RGB_GREEN]); b = GETJSAMPLE(inptr[RGB_BLUE]); - inptr += RGB_PIXELSIZE; /* Y */ outptr[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); + inptr += RGB_PIXELSIZE; } } } @@ -227,8 +239,8 @@ cmyk_ycck_convert (j_compress_ptr cinfo, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; + register int r, g, b; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2, outptr3; register JDIMENSION col; @@ -247,7 +259,6 @@ cmyk_ycck_convert (j_compress_ptr cinfo, b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); /* K passes through as-is */ outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ - inptr += 4; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't @@ -265,6 +276,49 @@ cmyk_ycck_convert (j_compress_ptr cinfo, outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); + inptr += 4; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * [R,G,B] to [R-G,G,B-G] conversion with modulo calculation + * (forward reversible color transform). + * This can be seen as an adaption of the general RGB->YCbCr + * conversion equation with Kr = Kb = 0, while replacing the + * normalization by modulo calculation. + */ + +METHODDEF(void) +rgb_rgb1_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register int r, g, b; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD + * (modulo) operator is equivalent to the bitmask operator AND. + */ + outptr0[col] = (JSAMPLE) ((r - g + CENTERJSAMPLE) & MAXJSAMPLE); + outptr1[col] = (JSAMPLE) g; + outptr2[col] = (JSAMPLE) ((b - g + CENTERJSAMPLE) & MAXJSAMPLE); + inptr += RGB_PIXELSIZE; } } } @@ -273,7 +327,7 @@ cmyk_ycck_convert (j_compress_ptr cinfo, /* * Convert some rows of samples to the JPEG colorspace. * This version handles grayscale output with no conversion. - * The source can be either plain grayscale or YCbCr (since Y == gray). + * The source can be either plain grayscale or YCC (since Y == gray). */ METHODDEF(void) @@ -281,16 +335,15 @@ grayscale_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { + int instride = cinfo->input_components; register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; - int instride = cinfo->input_components; while (--num_rows >= 0) { inptr = *input_buf++; - outptr = output_buf[0][output_row]; - output_row++; + outptr = output_buf[0][output_row++]; for (col = 0; col < num_cols; col++) { outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ inptr += instride; @@ -299,6 +352,39 @@ grayscale_convert (j_compress_ptr cinfo, } +/* + * Convert some rows of samples to the JPEG colorspace. + * No colorspace conversion, but change from interleaved + * to separate-planes representation. + */ + +METHODDEF(void) +rgb_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr0[col] = inptr[RGB_RED]; + outptr1[col] = inptr[RGB_GREEN]; + outptr2[col] = inptr[RGB_BLUE]; + inptr += RGB_PIXELSIZE; + } + } +} + + /* * Convert some rows of samples to the JPEG colorspace. * This version handles multi-component colorspaces without conversion. @@ -310,20 +396,20 @@ null_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { + int ci; + register int nc = cinfo->num_components; register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; - register int ci; - int nc = cinfo->num_components; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { /* It seems fastest to make a separate pass for each component. */ for (ci = 0; ci < nc; ci++) { - inptr = *input_buf; + inptr = input_buf[0] + ci; outptr = output_buf[ci][output_row]; for (col = 0; col < num_cols; col++) { - outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + *outptr++ = *inptr; /* don't need GETJSAMPLE() here */ inptr += nc; } } @@ -356,7 +442,7 @@ jinit_color_converter (j_compress_ptr cinfo) cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_converter)); - cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + cinfo->cconvert = &cconvert->pub; /* set start_pass to null method until we find out differently */ cconvert->pub.start_pass = null_method; @@ -368,13 +454,13 @@ jinit_color_converter (j_compress_ptr cinfo) break; case JCS_RGB: -#if RGB_PIXELSIZE != 3 + case JCS_BG_RGB: if (cinfo->input_components != RGB_PIXELSIZE) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; -#endif /* else share code with YCbCr */ case JCS_YCbCr: + case JCS_BG_YCC: if (cinfo->input_components != 3) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; @@ -391,41 +477,96 @@ jinit_color_converter (j_compress_ptr cinfo) break; } + /* Support color transform only for RGB colorspaces */ + if (cinfo->color_transform && + cinfo->jpeg_color_space != JCS_RGB && + cinfo->jpeg_color_space != JCS_BG_RGB) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + /* Check num_components, set conversion method based on requested space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_GRAYSCALE) + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + case JCS_YCbCr: + case JCS_BG_YCC: cconvert->pub.color_convert = grayscale_convert; - else if (cinfo->in_color_space == JCS_RGB) { + break; + case JCS_RGB: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_gray_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = grayscale_convert; - else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; case JCS_RGB: + case JCS_BG_RGB: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) - cconvert->pub.color_convert = null_convert; - else + if (cinfo->in_color_space == cinfo->jpeg_color_space) { + switch (cinfo->color_transform) { + case JCT_NONE: + cconvert->pub.color_convert = rgb_convert; + break; + case JCT_SUBTRACT_GREEN: + cconvert->pub.color_convert = rgb_rgb1_convert; + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB) { + switch (cinfo->in_color_space) { + case JCS_RGB: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_ycc_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) + break; + case JCS_YCbCr: cconvert->pub.color_convert = null_convert; - else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + break; + + case JCS_BG_YCC: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + switch (cinfo->in_color_space) { + case JCS_RGB: + /* For conversion from normal RGB input to BG_YCC representation, + * the Cb/Cr values are first computed as usual, and then + * quantized further after DCT processing by a factor of + * 2 in reference to the nominal quantization factor. + */ + /* need quantization scale by factor of 2 after DCT */ + cinfo->comp_info[1].component_needed = TRUE; + cinfo->comp_info[2].component_needed = TRUE; + /* compute normal YCC first */ + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + break; + case JCS_YCbCr: + /* need quantization scale by factor of 2 after DCT */ + cinfo->comp_info[1].component_needed = TRUE; + cinfo->comp_info[2].component_needed = TRUE; + /*FALLTHROUGH*/ + case JCS_BG_YCC: + /* Pass through for BG_YCC input */ + cconvert->pub.color_convert = null_convert; + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; case JCS_CMYK: @@ -440,13 +581,17 @@ jinit_color_converter (j_compress_ptr cinfo) case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_CMYK) { + switch (cinfo->in_color_space) { + case JCS_CMYK: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = cmyk_ycck_convert; - } else if (cinfo->in_color_space == JCS_YCCK) + break; + case JCS_YCCK: cconvert->pub.color_convert = null_convert; - else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; default: /* allow null conversion of JCS_UNKNOWN */ diff --git a/uppsrc/plugin/jpg/lib/jcdctmgr.c b/uppsrc/plugin/jpg/lib/jcdctmgr.c index d97141330..9daea85f6 100644 --- a/uppsrc/plugin/jpg/lib/jcdctmgr.c +++ b/uppsrc/plugin/jpg/lib/jcdctmgr.c @@ -1,7 +1,8 @@ /* * jcdctmgr.c * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -14,158 +15,51 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy codec */ #include "jdct.h" /* Private declarations for DCT subsystem */ /* Private subobject for this module */ typedef struct { - /* Pointer to the DCT routine actually in use */ - forward_DCT_method_ptr do_dct; + struct jpeg_forward_dct pub; /* public fields */ - /* The actual post-DCT divisors --- not identical to the quant table - * entries, because of scaling (especially for an unnormalized DCT). - * Each table is given in normal array order. - */ - DCTELEM * divisors[NUM_QUANT_TBLS]; + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct[MAX_COMPONENTS]; #ifdef DCT_FLOAT_SUPPORTED /* Same as above for the floating-point case. */ - float_DCT_method_ptr do_float_dct; - FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; + float_DCT_method_ptr do_float_dct[MAX_COMPONENTS]; #endif -} fdct_controller; +} my_fdct_controller; -typedef fdct_controller * fdct_ptr; +typedef my_fdct_controller * my_fdct_ptr; -/* - * Initialize for a processing pass. - * Verify that all referenced Q-tables are present, and set up - * the divisor table for each one. - * In the current implementation, DCT of all components is done during - * the first pass, even if only some components will be output in the - * first scan. Hence all components should be examined here. +/* The allocated post-DCT divisor tables -- big enough for any + * supported variant and not identical to the quant table entries, + * because of scaling (especially for an unnormalized DCT) -- + * are pointed to by dct_table in the per-component comp_info + * structures. Each table is given in normal array order. */ -METHODDEF(void) -start_pass_fdctmgr (j_compress_ptr cinfo) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; - int ci, qtblno, i; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - DCTELEM * dtbl; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - qtblno = compptr->quant_tbl_no; - /* Make sure specified quantization table is present */ - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - qtbl = cinfo->quant_tbl_ptrs[qtblno]; - /* Compute divisors for this quant table */ - /* We may do this more than once for same table, but it's not a big deal */ - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - /* For LL&M IDCT method, divisors are equal to raw quantization - * coefficients multiplied by 8 (to counteract scaling). - */ - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; - } - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, divisors 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 - * We apply a further scale factor of 8. - */ -#define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 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 - }; - SHIFT_TEMPS - - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = (DCTELEM) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-3); - } - } - break; -#endif +typedef union { + DCTELEM int_array[DCTSIZE2]; #ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, divisors 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 - * We apply a further scale factor of 8. - * What's actually stored is 1/divisor so that the inner loop can - * use a multiplication rather than a division. - */ - FAST_FLOAT * fdtbl; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - - if (fdct->float_divisors[qtblno] == NULL) { - fdct->float_divisors[qtblno] = (FAST_FLOAT *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(FAST_FLOAT)); - } - fdtbl = fdct->float_divisors[qtblno]; - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fdtbl[i] = (FAST_FLOAT) - (1.0 / (((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 8.0))); - i++; - } - } - } - break; + FAST_FLOAT float_array[DCTSIZE2]; +#endif +} divisor_table; + + +/* The current scaled-DCT routines require ISLOW-style divisor tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef DCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif #endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - } -} /* @@ -184,45 +78,17 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, /* This version is used for integer DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; - forward_DCT_method_ptr do_dct = fdct->do_dct; - DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + forward_DCT_method_ptr do_dct = fdct->do_dct[compptr->component_index]; + DCTELEM * divisors = (DCTELEM *) compptr->dct_table; DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; sample_data += start_row; /* fold in the vertical offset once */ - for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register DCTELEM *workspaceptr; - register JSAMPROW elemptr; - register int elemr; - - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { - elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; -#else - { register int elemc; - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - } - } -#endif - } - } - + for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { /* Perform the DCT */ - (*do_dct) (workspace); + (*do_dct) (workspace, sample_data, start_col); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register DCTELEM temp, qval; @@ -275,46 +141,17 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, /* This version is used for floating-point DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; - float_DCT_method_ptr do_dct = fdct->do_float_dct; - FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + float_DCT_method_ptr do_dct = fdct->do_float_dct[compptr->component_index]; + FAST_FLOAT * divisors = (FAST_FLOAT *) compptr->dct_table; FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; sample_data += start_row; /* fold in the vertical offset once */ - for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register FAST_FLOAT *workspaceptr; - register JSAMPROW elemptr; - register int elemr; - - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { - elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); -#else - { register int elemc; - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = (FAST_FLOAT) - (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - } - } -#endif - } - } - + for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { /* Perform the DCT */ - (*do_dct) (workspace); + (*do_dct) (workspace, sample_data, start_col); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register FAST_FLOAT temp; @@ -339,6 +176,280 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, #endif /* DCT_FLOAT_SUPPORTED */ +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + int ci, qtblno, i; + jpeg_component_info *compptr; + int method = 0; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper DCT routine for this component's scaling */ + switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { +#ifdef DCT_SCALING_SUPPORTED + case ((1 << 8) + 1): + fdct->do_dct[ci] = jpeg_fdct_1x1; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_2x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((3 << 8) + 3): + fdct->do_dct[ci] = jpeg_fdct_3x3; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_4x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((5 << 8) + 5): + fdct->do_dct[ci] = jpeg_fdct_5x5; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_6x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((7 << 8) + 7): + fdct->do_dct[ci] = jpeg_fdct_7x7; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((9 << 8) + 9): + fdct->do_dct[ci] = jpeg_fdct_9x9; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((10 << 8) + 10): + fdct->do_dct[ci] = jpeg_fdct_10x10; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((11 << 8) + 11): + fdct->do_dct[ci] = jpeg_fdct_11x11; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((12 << 8) + 12): + fdct->do_dct[ci] = jpeg_fdct_12x12; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((13 << 8) + 13): + fdct->do_dct[ci] = jpeg_fdct_13x13; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((14 << 8) + 14): + fdct->do_dct[ci] = jpeg_fdct_14x14; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((15 << 8) + 15): + fdct->do_dct[ci] = jpeg_fdct_15x15; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((16 << 8) + 16): + fdct->do_dct[ci] = jpeg_fdct_16x16; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((16 << 8) + 8): + fdct->do_dct[ci] = jpeg_fdct_16x8; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((14 << 8) + 7): + fdct->do_dct[ci] = jpeg_fdct_14x7; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((12 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_12x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((10 << 8) + 5): + fdct->do_dct[ci] = jpeg_fdct_10x5; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((8 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_8x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 3): + fdct->do_dct[ci] = jpeg_fdct_6x3; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_4x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 1): + fdct->do_dct[ci] = jpeg_fdct_2x1; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((8 << 8) + 16): + fdct->do_dct[ci] = jpeg_fdct_8x16; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((7 << 8) + 14): + fdct->do_dct[ci] = jpeg_fdct_7x14; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 12): + fdct->do_dct[ci] = jpeg_fdct_6x12; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((5 << 8) + 10): + fdct->do_dct[ci] = jpeg_fdct_5x10; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 8): + fdct->do_dct[ci] = jpeg_fdct_4x8; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((3 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_3x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_2x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((1 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_1x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; +#endif + case ((DCTSIZE << 8) + DCTSIZE): + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + fdct->do_dct[ci] = jpeg_fdct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + fdct->do_dct[ci] = jpeg_fdct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + fdct->do_float_dct[ci] = jpeg_fdct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); + break; + } + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Create divisor table from quant table */ + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + dtbl = (DCTELEM *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = + ((DCTELEM) qtbl->quantval[i]) << (compptr->component_needed ? 4 : 3); + } + fdct->pub.forward_DCT[ci] = forward_DCT; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors 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 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 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 + }; + SHIFT_TEMPS + + dtbl = (DCTELEM *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + compptr->component_needed ? CONST_BITS-4 : CONST_BITS-3); + } + } + fdct->pub.forward_DCT[ci] = forward_DCT; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors 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 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl = (FAST_FLOAT *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * + (compptr->component_needed ? 16.0 : 8.0))); + i++; + } + } + } + fdct->pub.forward_DCT[ci] = forward_DCT_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + /* * Initialize FDCT manager. */ @@ -346,45 +457,21 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jinit_forward_dct (j_compress_ptr cinfo) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - fdct_ptr fdct; - int i; + my_fdct_ptr fdct; + int ci; + jpeg_component_info *compptr; - fdct = (fdct_ptr) + fdct = (my_fdct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(fdct_controller)); - lossyc->fdct_private = (struct jpeg_forward_dct *) fdct; - lossyc->fdct_start_pass = start_pass_fdctmgr; + SIZEOF(my_fdct_controller)); + cinfo->fdct = &fdct->pub; + fdct->pub.start_pass = start_pass_fdctmgr; - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - lossyc->fdct_forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_islow; - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - lossyc->fdct_forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_ifast; - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - lossyc->fdct_forward_DCT = forward_DCT_float; - fdct->do_float_dct = jpeg_fdct_float; - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - - /* Mark divisor tables unallocated */ - for (i = 0; i < NUM_QUANT_TBLS; i++) { - fdct->divisors[i] = NULL; -#ifdef DCT_FLOAT_SUPPORTED - fdct->float_divisors[i] = NULL; -#endif + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate a divisor table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(divisor_table)); } } diff --git a/uppsrc/plugin/jpg/lib/jcdiffct.c b/uppsrc/plugin/jpg/lib/jcdiffct.c deleted file mode 100644 index 2346edf55..000000000 --- a/uppsrc/plugin/jpg/lib/jcdiffct.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * jcdiffct.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the difference buffer controller for compression. - * This controller is the top level of the lossless JPEG compressor proper. - * The difference buffer lies between prediction/differencing and entropy - * encoding. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" /* Private declarations for lossless codec */ - - -#ifdef C_LOSSLESS_SUPPORTED - -/* We use a full-image sample buffer when doing Huffman optimization, - * and also for writing multiple-scan JPEG files. In all cases, the - * full-image buffer is filled during the first pass, and the scaling, - * prediction and differencing steps are run during subsequent passes. - */ -#ifdef ENTROPY_OPT_SUPPORTED -#define FULL_SAMP_BUFFER_SUPPORTED -#else -#ifdef C_MULTISCAN_FILES_SUPPORTED -#define FULL_SAMP_BUFFER_SUPPORTED -#endif -#endif - - -/* Private buffer controller object */ - -typedef struct { - JDIMENSION iMCU_row_num; /* iMCU row # within image */ - JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point transformed samples */ - JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */ - JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ - - /* In multi-pass modes, we need a virtual sample array for each component. */ - jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; -} c_diff_controller; - -typedef c_diff_controller * c_diff_ptr; - - -/* Forward declarations */ -METHODDEF(boolean) compress_data - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -#ifdef FULL_SAMP_BUFFER_SUPPORTED -METHODDEF(boolean) compress_first_pass - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -METHODDEF(boolean) compress_output - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -#endif - - -LOCAL(void) -start_iMCU_row (j_compress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row */ -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - diff->MCU_rows_per_iMCU_row = 1; - } else { - if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1)) - diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - diff->mcu_ctr = 0; - diff->MCU_vert_offset = 0; -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; - - diff->iMCU_row_num = 0; - start_iMCU_row(cinfo); - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (diff->whole_image[0] != NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - losslsc->pub.compress_data = compress_data; - break; -#ifdef FULL_SAMP_BUFFER_SUPPORTED - case JBUF_SAVE_AND_PASS: - if (diff->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - losslsc->pub.compress_data = compress_first_pass; - break; - case JBUF_CRANK_DEST: - if (diff->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - losslsc->pub.compress_data = compress_output; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -#define SWAP_ROWS(rowa,rowb) {JSAMPROW temp; temp=rowa; rowa=rowb; rowb=temp;} - -/* - * Process some data in the single-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor rows for each component in the image. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - -METHODDEF(boolean) -compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION MCU_count; /* number of MCUs encoded */ -// JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int comp, ci, yoffset, samp_row, samp_rows, samps_across; - jpeg_component_info *compptr; - - /* Loop to write as much as one whole iMCU row */ - for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; - yoffset++) { - - MCU_col_num = diff->mcu_ctr; - - /* Scale and predict each scanline of the MCU-row separately. - * - * Note: We only do this if we are at the start of a MCU-row, ie, - * we don't want to reprocess a row suspended by the output. - */ - if (MCU_col_num == 0) { - for (comp = 0; comp < cinfo->comps_in_scan; comp++) { - compptr = cinfo->cur_comp_info[comp]; - ci = compptr->component_index; - if (diff->iMCU_row_num < last_iMCU_row) - samp_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here, since may not be set! */ - samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor); - if (samp_rows == 0) samp_rows = compptr->v_samp_factor; - else { - /* Fill dummy difference rows at the bottom edge with zeros, which - * will encode to the smallest amount of data. - */ - for (samp_row = samp_rows; samp_row < compptr->v_samp_factor; - samp_row++) - MEMZERO(diff->diff_buf[ci][samp_row], - jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); - } - } - samps_across = compptr->width_in_data_units; - - for (samp_row = 0; samp_row < samp_rows; samp_row++) { - (*losslsc->scaler_scale) (cinfo, - input_buf[ci][samp_row], - diff->cur_row[ci], samps_across); - (*losslsc->predict_difference[ci]) (cinfo, ci, - diff->cur_row[ci], - diff->prev_row[ci], - diff->diff_buf[ci][samp_row], - samps_across); - SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]); - } - } - } - - /* Try to write the MCU-row (or remaining portion of suspended MCU-row). */ - MCU_count = - (*losslsc->entropy_encode_mcus) (cinfo, - diff->diff_buf, yoffset, MCU_col_num, - cinfo->MCUs_per_row - MCU_col_num); - if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { - /* Suspension forced; update state counters and exit */ - diff->MCU_vert_offset = yoffset; - diff->mcu_ctr += MCU_col_num; - return FALSE; - } - - /* Completed an MCU row, but perhaps not an iMCU row */ - diff->mcu_ctr = 0; - } - - /* Completed the iMCU row, advance counters for next one */ - diff->iMCU_row_num++; - start_iMCU_row(cinfo); - return TRUE; -} - - -#ifdef FULL_SAMP_BUFFER_SUPPORTED - -/* - * Process some data in the first pass of a multi-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor rows for each component in the image. - * This amount of data is read from the source buffer and saved into the - * virtual arrays. - * - * We must also emit the data to the compressor. This is conveniently - * done by calling compress_output() after we've loaded the current strip - * of the virtual arrays. - * - * NB: input_buf contains a plane for each component in image. All components - * are loaded into the virtual arrays in this pass. However, it may be that - * only a subset of the components are emitted to the compressor during - * this first pass; be careful about looking at the scan-dependent variables - * (MCU dimensions, etc). - */ - -METHODDEF(boolean) -compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION samps_across; - int ci, samp_row, samp_rows; - JSAMPARRAY buffer[MAX_COMPONENTS]; - jpeg_component_info *compptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Align the virtual buffers for this component. */ - buffer[ci] = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, diff->whole_image[ci], - diff->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - - /* Count non-dummy sample rows in this iMCU row. */ - if (diff->iMCU_row_num < last_iMCU_row) - samp_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here, since may not be set! */ - samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor); - if (samp_rows == 0) samp_rows = compptr->v_samp_factor; - } - samps_across = compptr->width_in_data_units; - - /* Perform point transform scaling and prediction/differencing for all - * non-dummy rows in this iMCU row. Each call on these functions - * process a complete row of samples. - */ - for (samp_row = 0; samp_row < samp_rows; samp_row++) { - MEMCOPY(buffer[ci][samp_row], input_buf[ci][samp_row], - samps_across * SIZEOF(JSAMPLE)); - } - } - - /* NB: compress_output will increment iMCU_row_num if successful. - * A suspension return will result in redoing all the work above next time. - */ - - /* Emit data to the compressor, sharing code with subsequent passes */ - return compress_output(cinfo, input_buf); -} - - -/* - * Process some data in subsequent passes of a multi-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor rows for each component in the scan. - * The data is obtained from the virtual arrays and fed to the compressor. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf is ignored; it is likely to be a NULL pointer. - */ - -METHODDEF(boolean) -compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; -// JDIMENSION MCU_col_num; /* index of current MCU within row */ -// JDIMENSION MCU_count; /* number of MCUs encoded */ - int comp, ci; //, yoffset; - JSAMPARRAY buffer[MAX_COMPONENTS]; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. - * NB: during first pass, this is safe only because the buffers will - * already be aligned properly, so jmemmgr.c won't need to do any I/O. - */ - for (comp = 0; comp < cinfo->comps_in_scan; comp++) { - compptr = cinfo->cur_comp_info[comp]; - ci = compptr->component_index; - buffer[ci] = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, diff->whole_image[ci], - diff->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } - - return compress_data(cinfo, buffer); -} - -#endif /* FULL_SAMP_BUFFER_SUPPORTED */ - - -/* - * Initialize difference buffer controller. - */ - -GLOBAL(void) -jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - c_diff_ptr diff; - int ci, row; - jpeg_component_info *compptr; - - diff = (c_diff_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(c_diff_controller)); - losslsc->diff_private = (void *) diff; - losslsc->diff_start_pass = start_pass_diff; - - /* Create the prediction row buffers. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) 1); - diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) 1); - } - - /* Create the difference buffer. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) compptr->v_samp_factor); - /* Prefill difference rows with zeros. We do this because only actual - * data is placed in the buffers during prediction/differencing, leaving - * any dummy differences at the right edge as zeros, which will encode - * to the smallest amount of data. - */ - for (row = 0; row < compptr->v_samp_factor; row++) - MEMZERO(diff->diff_buf[ci][row], - jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); - } - - /* Create the sample buffer. */ - if (need_full_buffer) { -#ifdef FULL_SAMP_BUFFER_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor differences in each direction. */ - int ci; - jpeg_component_info *compptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_data_units, - (long) compptr->v_samp_factor), - (JDIMENSION) compptr->v_samp_factor); - } -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif - } else - diff->whole_image[0] = NULL; /* flag for no virtual arrays */ -} - -#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jchuff.c b/uppsrc/plugin/jpg/lib/jchuff.c index 10b52edc3..92fd974ca 100644 --- a/uppsrc/plugin/jpg/lib/jchuff.c +++ b/uppsrc/plugin/jpg/lib/jchuff.c @@ -1,18 +1,155 @@ /* * jchuff.c * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2006-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * - * This file contains Huffman entropy decoding routines which are shared - * by the sequential, progressive and lossless decoders. + * This file contains Huffman entropy encoding routines. + * Both sequential and progressive modes are supported in this single module. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + * + * We do not support output suspension for the progressive JPEG mode, since + * the library currently does not allow multiple-scan files to be written + * with output suspension. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jchuff.h" /* Declarations shared with jc*huff.c */ + + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; + + /* Following fields used only in progressive mode */ + + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ +} huff_entropy_encoder; + +typedef huff_entropy_encoder * huff_entropy_ptr; + +/* Working state while writing an MCU (sequential mode). + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif /* @@ -20,7 +157,7 @@ * This routine also performs some validation checks on the table. */ -GLOBAL(void) +LOCAL(void) jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, c_derived_tbl ** pdtbl) { @@ -49,7 +186,7 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(c_derived_tbl)); dtbl = *pdtbl; - + /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; @@ -62,7 +199,7 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, } huffsize[p] = 0; lastp = p; - + /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ @@ -82,7 +219,7 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, code <<= 1; si++; } - + /* Figure C.3: generate encoding tables */ /* These are code and size indexed by symbol value */ @@ -94,10 +231,10 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, /* This is also a convenient place to check for out-of-range * and duplicated VAL entries. We allow 0..255 for AC symbols - * but only 0..16 for DC. (We could constrain them further + * but only 0..15 for DC. (We could constrain them further * based on data depth and mode, but this seems enough.) */ - maxsymbol = isDC ? 16 : 255; + maxsymbol = isDC ? 15 : 255; for (p = 0; p < lastp; p++) { i = htbl->huffval[p]; @@ -109,6 +246,982 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, } +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte_s(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer_s(state)) \ + { action; } } + +/* Emit a byte */ +#define emit_byte_e(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer_e(entropy); } + + +LOCAL(boolean) +dump_buffer_s (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +LOCAL(void) +dump_buffer_e (huff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this case. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits_s (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer; + register int put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + /* mask off any extra bits in code */ + put_buffer = ((INT32) code) & ((((INT32) 1) << size) - 1); + + /* new number of bits in buffer */ + put_bits = size + state->cur.put_bits; + + put_buffer <<= 24 - put_bits; /* align incoming bits */ + + /* and merge with old buffer contents */ + put_buffer |= state->cur.put_buffer; + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte_s(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte_s(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +INLINE +LOCAL(void) +emit_bits_e (huff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer; + register int put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + /* mask off any extra bits in code */ + put_buffer = ((INT32) code) & ((((INT32) 1) << size) - 1); + + /* new number of bits in buffer */ + put_bits = size + entropy->saved.put_bits; + + put_buffer <<= 24 - put_bits; /* align incoming bits */ + + /* and merge with old buffer contents */ + put_buffer |= entropy->saved.put_buffer; + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte_e(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte_e(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->saved.put_buffer = put_buffer; /* update variables */ + entropy->saved.put_bits = put_bits; +} + + +LOCAL(boolean) +flush_bits_s (working_state * state) +{ + if (! emit_bits_s(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +LOCAL(void) +flush_bits_e (huff_entropy_ptr entropy) +{ + emit_bits_e(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->saved.put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->saved.put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_dc_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->dc_count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->dc_derived_tbls[tbl_no]; + emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +INLINE +LOCAL(void) +emit_ac_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->ac_count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->ac_derived_tbls[tbl_no]; + emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (huff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits_e(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (huff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_ac_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits_e(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart_s (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits_s(state)) + return FALSE; + + emit_byte_s(state, 0xFF, return FALSE); + emit_byte_s(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +LOCAL(void) +emit_restart_e (huff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits_e(entropy); + emit_byte_e(entropy, 0xFF); + emit_byte_e(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + int blkn, ci, tbl; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al); + + /* DC differences are figured on the point-transformed values. */ + temp2 = temp - entropy->saved.last_dc_val[ci]; + entropy->saved.last_dc_val[ci] = temp; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp = temp2; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_dc_symbol(entropy, tbl, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits_e(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + const int * natural_order; + JBLOCKROW block; + register int temp, temp2; + register int nbits; + register int r, k; + int Se, Al; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_ac_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits_e(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, + * although the spec is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int Al, blkn; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + Al = cinfo->Al; + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* We simply emit the Al'th bit of the DC coefficient value. */ + emit_bits_e(entropy, (unsigned int) (MCU_data[blkn][0][0] >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + const int * natural_order; + JBLOCKROW block; + register int temp; + register int r, k; + int Se, Al; + int EOB; + char *BR_buffer; + unsigned int BR; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[natural_order[k]] < 0) ? 0 : 1; + emit_bits_e(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int r, k; + int Se = state->cinfo->lim_Se; + const int * natural_order = state->cinfo->natural_order; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits_s(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k <= Se; k++) { + if ((temp2 = block[natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp = temp2; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + temp = (r << 4) + nbits; + if (! emit_bits_s(state, actbl->ehufco[temp], actbl->ehufsi[temp])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits_s(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits_s(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart_s(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + + if (cinfo->progressive_mode) { + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits_e(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + } else { + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits_s(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + } +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int r, k; + int Se = cinfo->lim_Se; + const int * natural_order = cinfo->natural_order; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k <= Se; k++) { + if ((temp = block[natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + /* * Generate the best Huffman code table for the given counts, fill htbl. * @@ -136,7 +1249,7 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, * So the extra complexity of an optimal algorithm doesn't seem worthwhile. */ -GLOBAL(void) +LOCAL(void) jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) { #define MAX_CLEN 32 /* assumed maximum initial code length */ @@ -153,7 +1266,7 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) MEMZERO(codesize, SIZEOF(codesize)); for (i = 0; i < 257; i++) others[i] = -1; /* init links to empty */ - + freq[256] = 1; /* make sure 256 has a nonzero count */ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees * that no real symbol is given code-value of all ones, because 256 @@ -188,7 +1301,7 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) /* Done if we've merged everything into one frequency */ if (c2 < 0) break; - + /* Else merge the two counts/trees */ freq[c1] += freq[c2]; freq[c2] = 0; @@ -199,9 +1312,9 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) c1 = others[c1]; codesize[c1]++; } - + others[c1] = c2; /* chain c2 onto c1's tree branch */ - + /* Increment the codesize of everything in c2's tree branch */ codesize[c2]++; while (others[c2] >= 0) { @@ -232,13 +1345,13 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) * shortest nonzero BITS entry is converted into a prefix for two code words * one bit longer. */ - + for (i = MAX_CLEN; i > 16; i--) { while (bits[i] > 0) { j = i - 2; /* find length of new prefix to be used */ while (bits[j] == 0) j--; - + bits[i] -= 2; /* remove two symbols */ bits[i-1]++; /* one goes in this length */ bits[j+1] += 2; /* two new symbols in this length */ @@ -250,10 +1363,10 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) while (bits[i] == 0) /* find largest codelength still in use */ i--; bits[i]--; - + /* Return final symbol counts (only for lengths 0..16) */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); - + /* Return a list of the symbols sorted by code length */ /* It's not real clear to me why we don't need to consider the codelength * changes made above, but the JPEG spec seems to think this works. @@ -271,3 +1384,190 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) /* Set sent_table FALSE so updated table will be written to JPEG file. */ htbl->sent_table = FALSE; } + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + if (cinfo->progressive_mode) + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (! did_dc[tbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[tbl]); + did_dc[tbl] = TRUE; + } + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (! did_ac[tbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[tbl]); + did_ac[tbl] = TRUE; + } + } + } +} + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (gather_statistics) + entropy->pub.finish_pass = finish_pass_gather; + else + entropy->pub.finish_pass = finish_pass_huff; + + if (cinfo->progressive_mode) { + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else { + entropy->pub.encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + + /* Initialize AC stuff */ + entropy->ac_tbl_no = cinfo->cur_comp_info[0]->ac_tbl_no; + entropy->EOBRUN = 0; + entropy->BE = 0; + } else { + if (gather_statistics) + entropy->pub.encode_mcu = encode_mcu_gather; + else + entropy->pub.encode_mcu = encode_mcu_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[tbl] == NULL) + entropy->dc_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, tbl, + & entropy->dc_derived_tbls[tbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (gather_statistics) { + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + if (entropy->ac_count_ptrs[tbl] == NULL) + entropy->ac_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + jpeg_make_c_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); + } + } + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_huff_encoder (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_encoder)); + cinfo->entropy = &entropy->pub; + entropy->pub.start_pass = start_pass_huff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; + } + + if (cinfo->progressive_mode) + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} diff --git a/uppsrc/plugin/jpg/lib/jchuff.h b/uppsrc/plugin/jpg/lib/jchuff.h deleted file mode 100644 index 69218a6c1..000000000 --- a/uppsrc/plugin/jpg/lib/jchuff.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * jchuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy encoding routines - * that are shared between the sequential encoder (jchuff.c) and the - * progressive encoder (jcphuff.c). No other modules need to see these. - */ - -/* The legal range of a DCT coefficient is - * -1024 .. +1023 for 8-bit data; - * -16384 .. +16383 for 12-bit data. - * Hence the magnitude should always fit in 10 or 14 bits respectively. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MAX_COEF_BITS 10 -#else -#define MAX_COEF_BITS 14 -#endif - -/* The legal range of a spatial difference is - * -32767 .. +32768. - * Hence the magnitude should always fit in 16 bits. - */ - -#define MAX_DIFF_BITS 16 - -/* Derived data constructed for each Huffman table */ - -typedef struct { - unsigned int ehufco[256]; /* code for each symbol */ - char ehufsi[256]; /* length of code for each symbol */ - /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ -} c_derived_tbl; - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_c_derived_tbl jMkCDerived -#define jpeg_gen_optimal_table jGenOptTbl -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Expand a Huffman table definition into the derived format */ -EXTERN(void) jpeg_make_c_derived_tbl - JPP((j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl)); - -/* Generate an optimal table definition given the specified counts */ -EXTERN(void) jpeg_gen_optimal_table - JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/uppsrc/plugin/jpg/lib/jcinit.c b/uppsrc/plugin/jpg/lib/jcinit.c index b4a166ccd..397b488ae 100644 --- a/uppsrc/plugin/jpg/lib/jcinit.c +++ b/uppsrc/plugin/jpg/lib/jcinit.c @@ -2,6 +2,7 @@ * jcinit.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -29,19 +30,45 @@ GLOBAL(void) jinit_compress_master (j_compress_ptr cinfo) { + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || + cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, FALSE /* full compression */); - /* Initialize compression codec */ - jinit_c_codec(cinfo); - /* Preprocessing */ if (! cinfo->raw_data_in) { jinit_color_converter(cinfo); jinit_downsampler(cinfo); jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); } + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) + jinit_arith_encoder(cinfo); + else { + jinit_huff_encoder(cinfo); + } + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); jinit_marker_writer(cinfo); diff --git a/uppsrc/plugin/jpg/lib/jclhuff.c b/uppsrc/plugin/jpg/lib/jclhuff.c deleted file mode 100644 index 850919ab9..000000000 --- a/uppsrc/plugin/jpg/lib/jclhuff.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * jclhuff.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy encoding routines for lossless JPEG. - * - * Much of the complexity here has to do with supporting output suspension. - * If the data destination module demands suspension, we want to be able to - * back up to the start of the current MCU. To do this, we copy state - * variables into local working storage, and update them back to the - * permanent JPEG objects only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" /* Private declarations for lossless codec */ -#include "jchuff.h" /* Declarations shared with jc*huff.c */ - - -/* Expanded entropy encoder object for Huffman encoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#define ASSIGN_STATE(dest,src) \ - ((dest).put_buffer = (src).put_buffer, \ - (dest).put_bits = (src).put_bits) -#endif - - -typedef struct { - int ci, yoffset, MCU_width; -} lhe_input_ptr_info; - - -typedef struct { - savable_state saved; /* Bit buffer at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - /* Pointers to derived tables to be used for each data unit within an MCU */ - c_derived_tbl * cur_tbls[C_MAX_DATA_UNITS_IN_MCU]; - -#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ - long * count_ptrs[NUM_HUFF_TBLS]; - - /* Pointers to stats tables to be used for each data unit within an MCU */ - long * cur_counts[C_MAX_DATA_UNITS_IN_MCU]; -#endif - - /* Pointers to the proper input difference row for each group of data units - * within an MCU. For each component, there are Vi groups of Hi data units. - */ - JDIFFROW input_ptr[C_MAX_DATA_UNITS_IN_MCU]; - - /* Number of input pointers in use for the current MCU. This is the sum - * of all Vi in the MCU. - */ - int num_input_ptrs; - - /* Information used for positioning the input pointers within the input - * difference rows. - */ - lhe_input_ptr_info input_ptr_info[C_MAX_DATA_UNITS_IN_MCU]; - - /* Index of the proper input pointer for each data unit within an MCU */ - int input_ptr_index[C_MAX_DATA_UNITS_IN_MCU]; - -} lhuff_entropy_encoder; - -typedef lhuff_entropy_encoder * lhuff_entropy_ptr; - -/* Working state while writing an MCU. - * This struct contains all the fields that are needed by subroutines. - */ - -typedef struct { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - savable_state cur; /* Current bit buffer & DC state */ - j_compress_ptr cinfo; /* dump_buffer needs access to this */ -} working_state; - - -/* Forward declarations */ -METHODDEF(JDIMENSION) encode_mcus_huff (j_compress_ptr cinfo, - JDIFFIMAGE diff_buf, - JDIMENSION MCU_row_num, - JDIMENSION MCU_col_num, - JDIMENSION nMCU); -METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); -#ifdef ENTROPY_OPT_SUPPORTED -METHODDEF(JDIMENSION) encode_mcus_gather (j_compress_ptr cinfo, - JDIFFIMAGE diff_buf, - JDIMENSION MCU_row_num, - JDIMENSION MCU_col_num, - JDIMENSION nMCU); -METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); -#endif - - -/* - * Initialize for a Huffman-compressed scan. - * If gather_statistics is TRUE, we do not output anything during the scan, - * just count the Huffman symbols used and generate Huffman code tables. - */ - -METHODDEF(void) -start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; - int ci, dctbl, sampn, ptrn, yoffset, xoffset; - jpeg_component_info * compptr; - - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - losslsc->entropy_encode_mcus = encode_mcus_gather; - losslsc->pub.entropy_finish_pass = finish_pass_gather; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - losslsc->entropy_encode_mcus = encode_mcus_huff; - losslsc->pub.entropy_finish_pass = finish_pass_huff; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - /* Check for invalid table indexes */ - /* (make_c_derived_tbl does this in the other path) */ - if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->count_ptrs[dctbl] == NULL) - entropy->count_ptrs[dctbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->count_ptrs[dctbl], 257 * SIZEOF(long)); -#endif - } else { - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, - & entropy->derived_tbls[dctbl]); - } - } - - /* Precalculate encoding info for each sample in an MCU of this scan */ - for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) { - compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; - ci = compptr->component_index; - /* ci = cinfo->MCU_membership[sampn]; - compptr = cinfo->cur_comp_info[ci];*/ - for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { - /* Precalculate the setup info for each input pointer */ - entropy->input_ptr_info[ptrn].ci = ci; - entropy->input_ptr_info[ptrn].yoffset = yoffset; - entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width; - for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { - /* Precalculate the input pointer index for each sample */ - entropy->input_ptr_index[sampn] = ptrn; - /* Precalculate which tables to use for each sample */ - entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; - entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no]; - } - } - } - entropy->num_input_ptrs = ptrn; - - /* Initialize bit buffer to empty */ - entropy->saved.put_buffer = 0; - entropy->saved.put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} - - -/* Outputting bytes to the file */ - -/* Emit a byte, taking 'action' if must suspend. */ -#define emit_byte(state,val,action) \ - { *(state)->next_output_byte++ = (JOCTET) (val); \ - if (--(state)->free_in_buffer == 0) \ - if (! dump_buffer(state)) \ - { action; } } - - -LOCAL(boolean) -dump_buffer (working_state * state) -/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ -{ - struct jpeg_destination_mgr * dest = state->cinfo->dest; - - if (! (*dest->empty_output_buffer) (state->cinfo)) - return FALSE; - /* After a successful buffer dump, must reset buffer pointers */ - state->next_output_byte = dest->next_output_byte; - state->free_in_buffer = dest->free_in_buffer; - return TRUE; -} - - -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - -INLINE -LOCAL(boolean) -emit_bits (working_state * state, unsigned int code, int size) -/* Emit some bits; return TRUE if successful, FALSE if must suspend */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = state->cur.put_bits; - - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); - - put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(state, c, return FALSE); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(state, 0, return FALSE); - } - put_buffer <<= 8; - put_bits -= 8; - } - - state->cur.put_buffer = put_buffer; /* update state variables */ - state->cur.put_bits = put_bits; - - return TRUE; -} - - -LOCAL(boolean) -flush_bits (working_state * state) -{ - if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ - return FALSE; - state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ - state->cur.put_bits = 0; - return TRUE; -} - - -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(boolean) -emit_restart (working_state * state, int restart_num) -{ -// int ci; - - if (! flush_bits(state)) - return FALSE; - - emit_byte(state, 0xFF, return FALSE); - emit_byte(state, JPEG_RST0 + restart_num, return FALSE); - - /* The restart counter is not updated until we successfully write the MCU. */ - - return TRUE; -} - - -/* - * Encode and output one nMCU's worth of Huffman-compressed differences. - */ - -METHODDEF(JDIMENSION) -encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, - JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, - JDIMENSION nMCU) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; - working_state state; - int mcu_num, sampn, ci, yoffset, MCU_width, ptrn; -// jpeg_component_info * compptr; - - /* Load up working state */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! emit_restart(&state, entropy->next_restart_num)) - return 0; - } - - /* Set input pointer locations based on MCU_col_num */ - for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { - ci = entropy->input_ptr_info[ptrn].ci; - yoffset = entropy->input_ptr_info[ptrn].yoffset; - MCU_width = entropy->input_ptr_info[ptrn].MCU_width; - entropy->input_ptr[ptrn] = - diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); - } - - for (mcu_num = 0; (unsigned)mcu_num < nMCU; mcu_num++) { - - /* Inner loop handles the samples in the MCU */ - for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { - register int temp, temp2; //, temp3; - register int nbits; - c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; - - /* Encode the difference per section H.1.2.2 */ - - /* Input the sample difference */ - temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; - - if (temp & 0x8000) { /* instead of temp < 0 */ - temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ - if (temp == 0) /* special case: magnitude = 32768 */ - temp2 = temp = 0x8000; - temp2 = ~ temp; /* one's complement of magnitude */ - } else { - temp &= 0x7FFF; /* abs value mod 2^16 */ - temp2 = temp; /* magnitude */ - } - - /* Find the number of bits needed for the magnitude of the difference */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range difference values. - */ - if (nbits > MAX_DIFF_BITS) - ERREXIT(cinfo, JERR_BAD_DIFF); - - /* Emit the Huffman-coded symbol for the number of bits */ - if (! emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) - return mcu_num; - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits && /* emit_bits rejects calls with size 0 */ - nbits != 16) /* special case: no bits should be emitted */ - if (! emit_bits(&state, (unsigned int) temp2, nbits)) - return mcu_num; - } - - /* Completed MCU, so update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - } - - return nMCU; -} - - -/* - * Finish up at the end of a Huffman-compressed scan. - */ - -METHODDEF(void) -finish_pass_huff (j_compress_ptr cinfo) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; - working_state state; - - /* Load up working state ... flush_bits needs it */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Flush out the last data */ - if (! flush_bits(&state)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - - /* Update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); -} - - -/* - * Huffman coding optimization. - * - * We first scan the supplied data and count the number of uses of each symbol - * that is to be Huffman-coded. (This process MUST agree with the code above.) - * Then we build a Huffman coding tree for the observed counts. - * Symbols which are not needed at all for the particular image are not - * assigned any code, which saves space in the DHT marker as well as in - * the compressed data. - */ - -#ifdef ENTROPY_OPT_SUPPORTED - -/* - * Trial-encode one nMCU's worth of Huffman-compressed differences. - * No data is actually output, so no suspension return is possible. - */ - -METHODDEF(JDIMENSION) -encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, - JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, - JDIMENSION nMCU) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; - int mcu_num, sampn, ci, yoffset, MCU_width, ptrn; -// jpeg_component_info * compptr; - - /* Take care of restart intervals if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - /* Update restart state */ - entropy->restarts_to_go = cinfo->restart_interval; - } - entropy->restarts_to_go--; - } - - /* Set input pointer locations based on MCU_col_num */ - for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { - ci = entropy->input_ptr_info[ptrn].ci; - yoffset = entropy->input_ptr_info[ptrn].yoffset; - MCU_width = entropy->input_ptr_info[ptrn].MCU_width; - entropy->input_ptr[ptrn] = - diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); - } - - for (mcu_num = 0; (unsigned)mcu_num < nMCU; mcu_num++) { - - /* Inner loop handles the samples in the MCU */ - for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { - register int temp; - register int nbits; -// c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; - long * counts = entropy->cur_counts[sampn]; - - /* Encode the difference per section H.1.2.2 */ - - /* Input the sample difference */ - temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; - - if (temp & 0x8000) { /* instead of temp < 0 */ - temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ - if (temp == 0) /* special case: magnitude = 32768 */ - temp = 0x8000; - } else - temp &= 0x7FFF; /* abs value mod 2^16 */ - - /* Find the number of bits needed for the magnitude of the difference */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range difference values. - */ - if (nbits > MAX_DIFF_BITS) - ERREXIT(cinfo, JERR_BAD_DIFF); - - /* Count the Huffman symbol for the number of bits */ - counts[nbits]++; - } - } - - return nMCU; -} - - -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - -METHODDEF(void) -finish_pass_gather (j_compress_ptr cinfo) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; - int ci, dctbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did_dc[NUM_HUFF_TBLS]; - - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ - MEMZERO(did_dc, SIZEOF(did_dc)); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - if (! did_dc[dctbl]) { - htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[dctbl]); - did_dc[dctbl] = TRUE; - } - } -} - - -#endif /* ENTROPY_OPT_SUPPORTED */ - - -METHODDEF(boolean) -need_optimization_pass (j_compress_ptr cinfo) -{ - return TRUE; -} - - -/* - * Module initialization routine for Huffman entropy encoding. - */ - -GLOBAL(void) -jinit_lhuff_encoder (j_compress_ptr cinfo) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - lhuff_entropy_ptr entropy; - int i; - - entropy = (lhuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(lhuff_entropy_encoder)); - losslsc->entropy_private = (struct jpeg_entropy_encoder *) entropy; - losslsc->pub.entropy_start_pass = start_pass_huff; - losslsc->pub.need_optimization_pass = need_optimization_pass; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; -#ifdef ENTROPY_OPT_SUPPORTED - entropy->count_ptrs[i] = NULL; -#endif - } -} diff --git a/uppsrc/plugin/jpg/lib/jclossls.c b/uppsrc/plugin/jpg/lib/jclossls.c deleted file mode 100644 index 669d4a947..000000000 --- a/uppsrc/plugin/jpg/lib/jclossls.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * jclossls.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the control logic for the lossless JPEG compressor. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" - - -#ifdef C_LOSSLESS_SUPPORTED - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - - (*losslsc->scaler_start_pass) (cinfo); - (*losslsc->predict_start_pass) (cinfo); - (*losslsc->diff_start_pass) (cinfo, pass_mode); -} - - -/* - * Initialize the lossless compression codec. - * This is called only once, during master selection. - */ - -GLOBAL(void) -jinit_lossless_c_codec(j_compress_ptr cinfo) -{ - j_lossless_c_ptr losslsc; - - /* Create subobject in permanent pool */ - losslsc = (j_lossless_c_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(jpeg_lossless_c_codec)); - cinfo->codec = (struct jpeg_c_codec *) losslsc; - - /* Initialize sub-modules */ - - /* Scaler */ - jinit_c_scaler(cinfo); - - /* Differencer */ - jinit_differencer(cinfo); - - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - jinit_lhuff_encoder(cinfo); - } - - /* Need a full-image difference buffer in any multi-pass mode. */ - jinit_c_diff_controller(cinfo, - (boolean) (cinfo->num_scans > 1 || - cinfo->optimize_coding)); - - /* Initialize method pointers. - * - * Note: entropy_start_pass and entropy_finish_pass are assigned in - * jclhuff.c and compress_data is assigned in jcdiffct.c. - */ - losslsc->pub.start_pass = start_pass; -} - -#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jclossy.c b/uppsrc/plugin/jpg/lib/jclossy.c deleted file mode 100644 index 3ea1074ac..000000000 --- a/uppsrc/plugin/jpg/lib/jclossy.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * jclossy.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the control logic for the lossy JPEG compressor. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossy.h" - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - - (*lossyc->fdct_start_pass) (cinfo); - (*lossyc->coef_start_pass) (cinfo, pass_mode); -} - - -/* - * Initialize the lossy compression codec. - * This is called only once, during master selection. - */ - -GLOBAL(void) -jinit_lossy_c_codec (j_compress_ptr cinfo) -{ - j_lossy_c_ptr lossyc; - - /* Create subobject in permanent pool */ - lossyc = (j_lossy_c_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(jpeg_lossy_c_codec)); - cinfo->codec = (struct jpeg_c_codec *) lossyc; - - /* Initialize sub-modules */ - - /* Forward DCT */ - jinit_forward_dct(cinfo); - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->process == JPROC_PROGRESSIVE) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_shuff_encoder(cinfo); - } - - /* Need a full-image coefficient buffer in any multi-pass mode. */ - jinit_c_coef_controller(cinfo, - (boolean) (cinfo->num_scans > 1 || - cinfo->optimize_coding)); - - /* Initialize method pointers. - * - * Note: entropy_start_pass and entropy_finish_pass are assigned in - * jcshuff.c or jcphuff.c and compress_data is assigned in jccoefct.c. - */ - lossyc->pub.start_pass = start_pass; -} diff --git a/uppsrc/plugin/jpg/lib/jcmainct.c b/uppsrc/plugin/jpg/lib/jcmainct.c index 267c89c95..29d53a22e 100644 --- a/uppsrc/plugin/jpg/lib/jcmainct.c +++ b/uppsrc/plugin/jpg/lib/jcmainct.c @@ -1,7 +1,8 @@ /* * jcmainct.c * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2012 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -68,32 +69,32 @@ METHODDEF(void) process_data_buffer_main METHODDEF(void) start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { - my_main_ptr main_ = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; /* Do nothing in raw-data mode. */ if (cinfo->raw_data_in) return; - main_->cur_iMCU_row = 0; /* initialize counters */ - main_->rowgroup_ctr = 0; - main_->suspended = FALSE; - main_->pass_mode = pass_mode; /* save mode for use by process_data */ + mainp->cur_iMCU_row = 0; /* initialize counters */ + mainp->rowgroup_ctr = 0; + mainp->suspended = FALSE; + mainp->pass_mode = pass_mode; /* save mode for use by process_data */ switch (pass_mode) { case JBUF_PASS_THRU: #ifdef FULL_MAIN_BUFFER_SUPPORTED - if (main_->whole_image[0] != NULL) + if (mainp->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif - main_->pub.process_data = process_data_simple_main; + mainp->pub.process_data = process_data_simple_main; break; #ifdef FULL_MAIN_BUFFER_SUPPORTED case JBUF_SAVE_SOURCE: case JBUF_CRANK_DEST: case JBUF_SAVE_AND_PASS: - if (main_->whole_image[0] == NULL) + if (mainp->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - main_->pub.process_data = process_data_buffer_main; + mainp->pub.process_data = process_data_buffer_main; break; #endif default: @@ -114,47 +115,46 @@ process_data_simple_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { - my_main_ptr main_ = (my_main_ptr) cinfo->main; - unsigned data_unit = cinfo->data_unit; + my_main_ptr mainp = (my_main_ptr) cinfo->main; - while (main_->cur_iMCU_row < cinfo->total_iMCU_rows) { - /* Read input data if we haven't filled the main_ buffer yet */ - if (main_->rowgroup_ctr < data_unit) + while (mainp->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (mainp->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size) (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, - main_->buffer, &main_->rowgroup_ctr, - (JDIMENSION) data_unit); + mainp->buffer, &mainp->rowgroup_ctr, + (JDIMENSION) cinfo->min_DCT_v_scaled_size); /* If we don't have a full iMCU row buffered, return to application for * more data. Note that preprocessor will always pad to fill the iMCU row * at the bottom of the image. */ - if (main_->rowgroup_ctr != data_unit) + if (mainp->rowgroup_ctr != (JDIMENSION) cinfo->min_DCT_v_scaled_size) return; /* Send the completed row to the compressor */ - if (! (*cinfo->codec->compress_data) (cinfo, main_->buffer)) { + if (! (*cinfo->coef->compress_data) (cinfo, mainp->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ - if (! main_->suspended) { + if (! mainp->suspended) { (*in_row_ctr)--; - main_->suspended = TRUE; + mainp->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous - * call suspended; then mark the main_ buffer empty. + * call suspended; then mark the main buffer empty. */ - if (main_->suspended) { + if (mainp->suspended) { (*in_row_ctr)++; - main_->suspended = FALSE; + mainp->suspended = FALSE; } - main_->rowgroup_ctr = 0; - main_->cur_iMCU_row++; + mainp->rowgroup_ctr = 0; + mainp->cur_iMCU_row++; } } @@ -171,26 +171,27 @@ process_data_buffer_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci; jpeg_component_info *compptr; - boolean writing = (main->pass_mode != JBUF_CRANK_DEST); - int data_unit = cinfo->data_unit; + boolean writing = (mainp->pass_mode != JBUF_CRANK_DEST); - while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + while (mainp->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Realign the virtual buffers if at the start of an iMCU row. */ - if (main->rowgroup_ctr == 0) { + if (mainp->rowgroup_ctr == 0) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main->buffer[ci] = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, main->whole_image[ci], - main->cur_iMCU_row * (compptr->v_samp_factor * data_unit), - (JDIMENSION) (compptr->v_samp_factor * data_unit), writing); + mainp->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, mainp->whole_image[ci], mainp->cur_iMCU_row * + ((JDIMENSION) (compptr->v_samp_factor * cinfo->min_DCT_v_scaled_size)), + (JDIMENSION) (compptr->v_samp_factor * cinfo->min_DCT_v_scaled_size), + writing); } /* In a read pass, pretend we just read some source data. */ if (! writing) { - *in_row_ctr += cinfo->max_v_samp_factor * data_unit; - main->rowgroup_ctr = data_unit; + *in_row_ctr += (JDIMENSION) + (cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size); + mainp->rowgroup_ctr = (JDIMENSION) cinfo->min_DCT_v_scaled_size; } } @@ -199,40 +200,40 @@ process_data_buffer_main (j_compress_ptr cinfo, if (writing) { (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, - main->buffer, &main->rowgroup_ctr, - (JDIMENSION) data_unit); + mainp->buffer, &mainp->rowgroup_ctr, + (JDIMENSION) cinfo->min_DCT_v_scaled_size); /* Return to application if we need more data to fill the iMCU row. */ - if (main->rowgroup_ctr < data_unit) + if (mainp->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size) return; } /* Emit data, unless this is a sink-only pass. */ - if (main->pass_mode != JBUF_SAVE_SOURCE) { - if (! (*cinfo->codec->compress_data) (cinfo, main->buffer)) { + if (mainp->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, mainp->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ - if (! main->suspended) { + if (! mainp->suspended) { (*in_row_ctr)--; - main->suspended = TRUE; + mainp->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ - if (main->suspended) { + if (mainp->suspended) { (*in_row_ctr)++; - main->suspended = FALSE; + mainp->suspended = FALSE; } } /* If get here, we are done with this iMCU row. Mark buffer empty. */ - main->rowgroup_ctr = 0; - main->cur_iMCU_row++; + mainp->rowgroup_ctr = 0; + mainp->cur_iMCU_row++; } } @@ -246,16 +247,15 @@ process_data_buffer_main (j_compress_ptr cinfo, GLOBAL(void) jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) { - my_main_ptr main_; + my_main_ptr mainp; int ci; jpeg_component_info *compptr; - int data_unit = cinfo->data_unit; - main_ = (my_main_ptr) + mainp = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_c_main_controller *) main_; - main_->pub.start_pass = start_pass_main; + cinfo->main = &mainp->pub; + mainp->pub.start_pass = start_pass_main; /* We don't need to create a buffer in raw-data mode. */ if (cinfo->raw_data_in) @@ -270,27 +270,28 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) /* Note we pad the bottom to a multiple of the iMCU height */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main_->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + mainp->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - compptr->width_in_data_units * data_unit, - (JDIMENSION) jround_up((long) compptr->height_in_data_units, - (long) compptr->v_samp_factor) * data_unit, - (JDIMENSION) (compptr->v_samp_factor * data_unit)); + compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), + ((JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor)) * + ((JDIMENSION) cinfo->min_DCT_v_scaled_size), + (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { #ifdef FULL_MAIN_BUFFER_SUPPORTED - main_->whole_image[0] = NULL; /* flag for no virtual arrays */ + mainp->whole_image[0] = NULL; /* flag for no virtual arrays */ #endif /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main_->buffer[ci] = (*cinfo->mem->alloc_sarray) + mainp->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_data_units * data_unit, - (JDIMENSION) (compptr->v_samp_factor * data_unit)); + compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), + (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); } } } diff --git a/uppsrc/plugin/jpg/lib/jcmarker.c b/uppsrc/plugin/jpg/lib/jcmarker.c index eac019025..f2cd7a393 100644 --- a/uppsrc/plugin/jpg/lib/jcmarker.c +++ b/uppsrc/plugin/jpg/lib/jcmarker.c @@ -2,6 +2,7 @@ * jcmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -72,6 +73,7 @@ typedef enum { /* JPEG marker codes */ M_APP15 = 0xef, M_JPG0 = 0xf0, + M_JPG8 = 0xf8, M_JPG13 = 0xfd, M_COM = 0xfe, @@ -153,21 +155,22 @@ emit_dqt (j_compress_ptr cinfo, int index) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); prec = 0; - for (i = 0; i < DCTSIZE2; i++) { - if (qtbl->quantval[i] > 255) + for (i = 0; i <= cinfo->lim_Se; i++) { + if (qtbl->quantval[cinfo->natural_order[i]] > 255) prec = 1; } if (! qtbl->sent_table) { emit_marker(cinfo, M_DQT); - emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + emit_2bytes(cinfo, + prec ? cinfo->lim_Se * 2 + 2 + 1 + 2 : cinfo->lim_Se + 1 + 1 + 2); emit_byte(cinfo, index + (prec<<4)); - for (i = 0; i < DCTSIZE2; i++) { + for (i = 0; i <= cinfo->lim_Se; i++) { /* The table entries must be emitted in zigzag order. */ - unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + unsigned int qval = qtbl->quantval[cinfo->natural_order[i]]; if (prec) emit_byte(cinfo, (int) (qval >> 8)); emit_byte(cinfo, (int) (qval & 0xFF)); @@ -186,7 +189,7 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) { JHUFF_TBL * htbl; int length, i; - + if (is_ac) { htbl = cinfo->ac_huff_tbl_ptrs[index]; index += 0x10; /* output index has AC bit set */ @@ -196,23 +199,23 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); - + if (! htbl->sent_table) { emit_marker(cinfo, M_DHT); - + length = 0; for (i = 1; i <= 16; i++) length += htbl->bits[i]; - + emit_2bytes(cinfo, length + 2 + 1 + 16); emit_byte(cinfo, index); - + for (i = 1; i <= 16; i++) emit_byte(cinfo, htbl->bits[i]); - + for (i = 0; i < length; i++) emit_byte(cinfo, htbl->huffval[i]); - + htbl->sent_table = TRUE; } } @@ -235,26 +238,32 @@ emit_dac (j_compress_ptr cinfo) for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; - dc_in_use[compptr->dc_tbl_no] = 1; - ac_in_use[compptr->ac_tbl_no] = 1; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) + dc_in_use[compptr->dc_tbl_no] = 1; + /* AC needs no table when not present */ + if (cinfo->Se) + ac_in_use[compptr->ac_tbl_no] = 1; } length = 0; for (i = 0; i < NUM_ARITH_TBLS; i++) length += dc_in_use[i] + ac_in_use[i]; - emit_marker(cinfo, M_DAC); + if (length) { + emit_marker(cinfo, M_DAC); - emit_2bytes(cinfo, length*2 + 2); + emit_2bytes(cinfo, length*2 + 2); - for (i = 0; i < NUM_ARITH_TBLS; i++) { - if (dc_in_use[i]) { - emit_byte(cinfo, i); - emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); - } - if (ac_in_use[i]) { - emit_byte(cinfo, i + 0x10); - emit_byte(cinfo, cinfo->arith_ac_K[i]); + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } } } #endif /* C_ARITH_CODING_SUPPORTED */ @@ -266,32 +275,63 @@ emit_dri (j_compress_ptr cinfo) /* Emit a DRI marker */ { emit_marker(cinfo, M_DRI); - + emit_2bytes(cinfo, 4); /* fixed length */ emit_2bytes(cinfo, (int) cinfo->restart_interval); } +LOCAL(void) +emit_lse_ict (j_compress_ptr cinfo) +/* Emit an LSE inverse color transform specification marker */ +{ + /* Support only 1 transform */ + if (cinfo->color_transform != JCT_SUBTRACT_GREEN || + cinfo->num_components < 3) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + + emit_marker(cinfo, M_JPG8); + + emit_2bytes(cinfo, 24); /* fixed length */ + + emit_byte(cinfo, 0x0D); /* ID inverse transform specification */ + emit_2bytes(cinfo, MAXJSAMPLE); /* MAXTRANS */ + emit_byte(cinfo, 3); /* Nt=3 */ + emit_byte(cinfo, cinfo->comp_info[1].component_id); + emit_byte(cinfo, cinfo->comp_info[0].component_id); + emit_byte(cinfo, cinfo->comp_info[2].component_id); + emit_byte(cinfo, 0x80); /* F1: CENTER1=1, NORM1=0 */ + emit_2bytes(cinfo, 0); /* A(1,1)=0 */ + emit_2bytes(cinfo, 0); /* A(1,2)=0 */ + emit_byte(cinfo, 0); /* F2: CENTER2=0, NORM2=0 */ + emit_2bytes(cinfo, 1); /* A(2,1)=1 */ + emit_2bytes(cinfo, 0); /* A(2,2)=0 */ + emit_byte(cinfo, 0); /* F3: CENTER3=0, NORM3=0 */ + emit_2bytes(cinfo, 1); /* A(3,1)=1 */ + emit_2bytes(cinfo, 0); /* A(3,2)=0 */ +} + + LOCAL(void) emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) /* Emit a SOF marker */ { int ci; jpeg_component_info *compptr; - + emit_marker(cinfo, code); - + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ /* Make sure image isn't bigger than SOF field can handle */ - if ((long) cinfo->image_height > 65535L || - (long) cinfo->image_width > 65535L) + if ((long) cinfo->jpeg_height > 65535L || + (long) cinfo->jpeg_width > 65535L) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); emit_byte(cinfo, cinfo->data_precision); - emit_2bytes(cinfo, (int) cinfo->image_height); - emit_2bytes(cinfo, (int) cinfo->image_width); + emit_2bytes(cinfo, (int) cinfo->jpeg_height); + emit_2bytes(cinfo, (int) cinfo->jpeg_width); emit_byte(cinfo, cinfo->num_components); @@ -310,32 +350,26 @@ emit_sos (j_compress_ptr cinfo) { int i, td, ta; jpeg_component_info *compptr; - + emit_marker(cinfo, M_SOS); - + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ - + emit_byte(cinfo, cinfo->comps_in_scan); - + for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; emit_byte(cinfo, compptr->component_id); - td = compptr->dc_tbl_no; - ta = compptr->ac_tbl_no; - if (cinfo->process == JPROC_PROGRESSIVE) { - /* Progressive mode: only DC or only AC tables are used in one scan; - * furthermore, Huffman coding of DC refinement uses no table at all. - * We emit 0 for unused field(s); this is recommended by the P&M text - * but does not seem to be specified in the standard. - */ - if (cinfo->Ss == 0) { - ta = 0; /* DC scan */ - if (cinfo->Ah != 0 && !cinfo->arith_code) - td = 0; /* no DC table either */ - } else { - td = 0; /* AC scan */ - } - } + + /* We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + + /* DC needs no table for refinement scan */ + td = cinfo->Ss == 0 && cinfo->Ah == 0 ? compptr->dc_tbl_no : 0; + /* AC needs no table when not present */ + ta = cinfo->Se ? compptr->ac_tbl_no : 0; + emit_byte(cinfo, (td << 4) + ta); } @@ -345,6 +379,22 @@ emit_sos (j_compress_ptr cinfo) } +LOCAL(void) +emit_pseudo_sos (j_compress_ptr cinfo) +/* Emit a pseudo SOS marker */ +{ + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 + 1 + 3); /* length */ + + emit_byte(cinfo, 0); /* Ns */ + + emit_byte(cinfo, 0); /* Ss */ + emit_byte(cinfo, cinfo->block_size * cinfo->block_size - 1); /* Se */ + emit_byte(cinfo, 0); /* Ah/Al */ +} + + LOCAL(void) emit_jfif_app0 (j_compress_ptr cinfo) /* Emit a JFIF-compliant APP0 marker */ @@ -360,9 +410,9 @@ emit_jfif_app0 (j_compress_ptr cinfo) * Thumbnail X size (1 byte) * Thumbnail Y size (1 byte) */ - + emit_marker(cinfo, M_APP0); - + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ @@ -399,9 +449,9 @@ emit_adobe_app14 (j_compress_ptr cinfo) * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with * whether the encoder performed a transformation, which is pretty useless. */ - + emit_marker(cinfo, M_APP14); - + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ @@ -458,8 +508,8 @@ write_marker_byte (j_compress_ptr cinfo, int val) * Write datastream header. * This consists of an SOI and optional APPn markers. * We recommend use of the JFIF marker, but not the Adobe marker, - * when using YCbCr or grayscale data. The JFIF marker should NOT - * be used for any other JPEG colorspace. The Adobe marker is helpful + * when using YCbCr or grayscale data. The JFIF marker is also used + * for other standard JPEG colorspaces. The Adobe marker is helpful * to distinguish RGB, CMYK, and YCCK colorspaces. * Note that an application can write additional header markers after * jpeg_start_compress returns. @@ -484,7 +534,8 @@ write_file_header (j_compress_ptr cinfo) /* * Write frame header. - * This consists of DQT and SOFn markers. + * This consists of DQT and SOFn markers, + * a conditional LSE marker and a conditional pseudo SOS marker. * Note that we do not emit the SOF until we have emitted the DQT(s). * This avoids compatibility problems with incorrect implementations that * try to error-check the quant table numbers as soon as they see the SOF. @@ -496,24 +547,22 @@ write_frame_header (j_compress_ptr cinfo) int ci, prec; boolean is_baseline; jpeg_component_info *compptr; - - if (cinfo->process != JPROC_LOSSLESS) { - /* Emit DQT for each quantization table. - * Note that emit_dqt() suppresses any duplicate tables. - */ - prec = 0; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - prec += emit_dqt(cinfo, compptr->quant_tbl_no); - } - /* now prec is nonzero iff there are any 16-bit quant tables. */ + + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + prec = 0; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); } + /* now prec is nonzero iff there are any 16-bit quant tables. */ /* Check for a non-baseline specification. * Note we assume that Huffman table numbers won't be changed later. */ - if (cinfo->arith_code || cinfo->process != JPROC_SEQUENTIAL || - cinfo->data_precision != 8) { + if (cinfo->arith_code || cinfo->progressive_mode || + cinfo->data_precision != 8 || cinfo->block_size != DCTSIZE) { is_baseline = FALSE; } else { is_baseline = TRUE; @@ -531,17 +580,26 @@ write_frame_header (j_compress_ptr cinfo) /* Emit the proper SOF marker */ if (cinfo->arith_code) { - emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */ + else + emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ } else { - if (cinfo->process == JPROC_PROGRESSIVE) + if (cinfo->progressive_mode) emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ - else if (cinfo->process == JPROC_LOSSLESS) - emit_sof(cinfo, M_SOF3); /* SOF code for lossless Huffman */ else if (is_baseline) emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ else emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ } + + /* Check to emit LSE inverse color transform specification marker */ + if (cinfo->color_transform) + emit_lse_ict(cinfo); + + /* Check to emit pseudo SOS marker */ + if (cinfo->progressive_mode && cinfo->block_size != DCTSIZE) + emit_pseudo_sos(cinfo); } @@ -570,22 +628,12 @@ write_scan_header (j_compress_ptr cinfo) */ for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; - if (cinfo->process == JPROC_PROGRESSIVE) { - /* Progressive mode: only DC or only AC tables are used in one scan */ - if (cinfo->Ss == 0) { - if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - } else { - emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } - } else if (cinfo->process == JPROC_LOSSLESS) { - /* Lossless mode: only DC tables are used */ - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - } else { - /* Sequential mode: need both DC and AC tables */ + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + /* AC needs no table when not present */ + if (cinfo->Se) emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } } } @@ -657,7 +705,7 @@ jinit_marker_writer (j_compress_ptr cinfo) marker = (my_marker_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_marker_writer)); - cinfo->marker = (struct jpeg_marker_writer *) marker; + cinfo->marker = &marker->pub; /* Initialize method pointers */ marker->pub.write_file_header = write_file_header; marker->pub.write_frame_header = write_frame_header; diff --git a/uppsrc/plugin/jpg/lib/jcmaster.c b/uppsrc/plugin/jpg/lib/jcmaster.c index bb5fc3bab..431744ebe 100644 --- a/uppsrc/plugin/jpg/lib/jcmaster.c +++ b/uppsrc/plugin/jpg/lib/jcmaster.c @@ -1,20 +1,20 @@ /* * jcmaster.c * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains master control logic for the JPEG compressor. * These routines are concerned with parameter validation, initial setup, - * and inter-pass control (determining the number of passes and the work + * and inter-pass control (determining the number of passes and the work * to be done in each pass). */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy codec */ /* Private state */ @@ -43,34 +43,222 @@ typedef my_comp_master * my_master_ptr; * Support routines that do various essential calculations. */ -LOCAL(void) -initial_setup (j_compress_ptr cinfo) +/* + * Compute JPEG image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + */ + +GLOBAL(void) +jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { - int ci; +#ifdef DCT_SCALING_SUPPORTED + + /* Sanity check on input image dimensions to prevent overflow in + * following calculation. + * We do check jpeg_width and jpeg_height in initial_setup below, + * but image_width and image_height can come from arbitrary data, + * and we need some space for multiplication by block_size. + */ + if (((long) cinfo->image_width >> 24) || ((long) cinfo->image_height >> 24)) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Compute actual JPEG image dimensions and DCT scaling choices. */ + if (cinfo->scale_num >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/1 scaling */ + cinfo->jpeg_width = cinfo->image_width * cinfo->block_size; + cinfo->jpeg_height = cinfo->image_height * cinfo->block_size; + cinfo->min_DCT_h_scaled_size = 1; + cinfo->min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * 2 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/2 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 2L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 2L); + cinfo->min_DCT_h_scaled_size = 2; + cinfo->min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/3 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 3L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 3L); + cinfo->min_DCT_h_scaled_size = 3; + cinfo->min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * 4 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/4 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 4L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 4L); + cinfo->min_DCT_h_scaled_size = 4; + cinfo->min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/5 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 5L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 5L); + cinfo->min_DCT_h_scaled_size = 5; + cinfo->min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * 6 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/6 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 6L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 6L); + cinfo->min_DCT_h_scaled_size = 6; + cinfo->min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/7 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 7L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 7L); + cinfo->min_DCT_h_scaled_size = 7; + cinfo->min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * 8 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/8 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 8L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 8L); + cinfo->min_DCT_h_scaled_size = 8; + cinfo->min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * 9 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/9 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 9L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 9L); + cinfo->min_DCT_h_scaled_size = 9; + cinfo->min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * 10 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/10 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 10L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 10L); + cinfo->min_DCT_h_scaled_size = 10; + cinfo->min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * 11 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/11 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 11L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 11L); + cinfo->min_DCT_h_scaled_size = 11; + cinfo->min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * 12 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/12 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 12L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 12L); + cinfo->min_DCT_h_scaled_size = 12; + cinfo->min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * 13 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/13 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 13L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 13L); + cinfo->min_DCT_h_scaled_size = 13; + cinfo->min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * 14 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/14 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 14L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 14L); + cinfo->min_DCT_h_scaled_size = 14; + cinfo->min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * 15 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/15 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 15L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 15L); + cinfo->min_DCT_h_scaled_size = 15; + cinfo->min_DCT_v_scaled_size = 15; + } else { + /* Provide block_size/16 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 16L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 16L); + cinfo->min_DCT_h_scaled_size = 16; + cinfo->min_DCT_v_scaled_size = 16; + } + +#else /* !DCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->jpeg_width = cinfo->image_width; + cinfo->jpeg_height = cinfo->image_height; + cinfo->min_DCT_h_scaled_size = DCTSIZE; + cinfo->min_DCT_v_scaled_size = DCTSIZE; + +#endif /* DCT_SCALING_SUPPORTED */ +} + + +LOCAL(void) +jpeg_calc_trans_dimensions (j_compress_ptr cinfo) +{ + if (cinfo->min_DCT_h_scaled_size != cinfo->min_DCT_v_scaled_size) + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); + + cinfo->block_size = cinfo->min_DCT_h_scaled_size; +} + + +LOCAL(void) +initial_setup (j_compress_ptr cinfo, boolean transcode_only) +/* Do computations that are needed before master selection phase */ +{ + int ci, ssize; jpeg_component_info *compptr; - long samplesperrow; - JDIMENSION jd_samplesperrow; - int data_unit = cinfo->data_unit; + + if (transcode_only) + jpeg_calc_trans_dimensions(cinfo); + else + jpeg_calc_jpeg_dimensions(cinfo); + + /* Sanity check on block_size */ + if (cinfo->block_size < 1 || cinfo->block_size > 16) + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, cinfo->block_size, cinfo->block_size); + + /* Derive natural_order from block_size */ + switch (cinfo->block_size) { + case 2: cinfo->natural_order = jpeg_natural_order2; break; + case 3: cinfo->natural_order = jpeg_natural_order3; break; + case 4: cinfo->natural_order = jpeg_natural_order4; break; + case 5: cinfo->natural_order = jpeg_natural_order5; break; + case 6: cinfo->natural_order = jpeg_natural_order6; break; + case 7: cinfo->natural_order = jpeg_natural_order7; break; + default: cinfo->natural_order = jpeg_natural_order; break; + } + + /* Derive lim_Se from block_size */ + cinfo->lim_Se = cinfo->block_size < DCTSIZE ? + cinfo->block_size * cinfo->block_size - 1 : DCTSIZE2-1; /* Sanity check on image dimensions */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0 || cinfo->input_components <= 0) + if (cinfo->jpeg_height <= 0 || cinfo->jpeg_width <= 0 || + cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Make sure image isn't bigger than I can handle */ - if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + if ((long) cinfo->jpeg_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->jpeg_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - /* Width of an input scanline must be representable as JDIMENSION. */ - samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; - jd_samplesperrow = (JDIMENSION) samplesperrow; - if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) + /* Only 8 to 12 bits data precision are supported for DCT based JPEG */ + if (cinfo->data_precision < 8 || cinfo->data_precision > 12) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ @@ -97,48 +285,73 @@ initial_setup (j_compress_ptr cinfo) ci++, compptr++) { /* Fill in the correct component_index value; don't rely on application */ compptr->component_index = ci; - /* For compression, we never do any codec-based processing. */ - compptr->codec_data_unit = data_unit; - /* Size in data units */ - compptr->width_in_data_units = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * data_unit)); - compptr->height_in_data_units = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * data_unit)); + /* In selecting the actual DCT scaling for each component, we try to + * scale down the chroma components via DCT scaling rather than downsampling. + * This saves time if the downsampler gets to use 1:1 scaling. + * Note this code adapts subsampling ratios which are powers of 2. + */ + ssize = 1; +#ifdef DCT_SCALING_SUPPORTED + while (cinfo->min_DCT_h_scaled_size * ssize <= + (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } +#endif + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; + ssize = 1; +#ifdef DCT_SCALING_SUPPORTED + while (cinfo->min_DCT_v_scaled_size * ssize <= + (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } +#endif + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; + + /* We don't support DCT ratios larger than 2. */ + if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; + else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) + compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; + + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); + jdiv_round_up((long) cinfo->jpeg_width * + (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed (this flag isn't actually used for compression) */ - compptr->component_needed = TRUE; + jdiv_round_up((long) cinfo->jpeg_height * + (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + /* Don't need quantization scale after DCT, + * until color conversion says otherwise. + */ + compptr->component_needed = FALSE; } /* Compute number of fully interleaved MCU rows (number of times that * main controller will call coefficient controller). */ cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*data_unit)); + jdiv_round_up((long) cinfo->jpeg_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); } -#ifdef C_MULTISCAN_FILES_SUPPORTED -#define NEED_SCAN_SCRIPT -#else -#ifdef C_LOSSLESS_SUPPORTED -#define NEED_SCAN_SCRIPT -#endif -#endif -#ifdef NEED_SCAN_SCRIPT +#ifdef C_MULTISCAN_FILES_SUPPORTED LOCAL(void) validate_script (j_compress_ptr cinfo) /* Verify that the scan script in cinfo->scan_info[] is valid; also - * determine whether it uses progressive JPEG, and set cinfo->process. + * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. */ { const jpeg_scan_info * scanptr; @@ -154,37 +367,23 @@ validate_script (j_compress_ptr cinfo) if (cinfo->num_scans <= 0) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); -#ifndef C_MULTISCAN_FILES_SUPPORTED - if (cinfo->num_scans > 1) - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - - scanptr = cinfo->scan_info; - if (cinfo->lossless) { -#ifdef C_LOSSLESS_SUPPORTED - cinfo->process = JPROC_LOSSLESS; - for (ci = 0; ci < cinfo->num_components; ci++) - component_sent[ci] = FALSE; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; * for progressive JPEG, no scan can have this. */ - else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { #ifdef C_PROGRESSIVE_SUPPORTED - cinfo->process = JPROC_PROGRESSIVE; + cinfo->progressive_mode = TRUE; last_bitpos_ptr = & last_bitpos[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) + for (ci = 0; ci < cinfo->num_components; ci++) for (coefi = 0; coefi < DCTSIZE2; coefi++) *last_bitpos_ptr++ = -1; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - cinfo->process = JPROC_SEQUENTIAL; - for (ci = 0; ci < cinfo->num_components; ci++) + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) component_sent[ci] = FALSE; } @@ -206,26 +405,7 @@ validate_script (j_compress_ptr cinfo) Se = scanptr->Se; Ah = scanptr->Ah; Al = scanptr->Al; - if (cinfo->process == JPROC_LOSSLESS) { -#ifdef C_LOSSLESS_SUPPORTED - /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that - * seems wrong: the upper bound ought to depend on data precision. - * Perhaps they really meant 0..N-1 for N-bit precision, which is what - * we allow here. - */ - if (Ss < 1 || Ss > 7 || /* predictor selector */ - Se != 0 || Ah != 0 || - Al < 0 || Al >= cinfo->data_precision) /* point transform */ - ERREXIT1(cinfo, JERR_BAD_LOSSLESS_SCRIPT, scanno); - /* Make sure components are not sent twice */ - for (ci = 0; ci < ncomps; ci++) { - thisi = scanptr->component_index[ci]; - if (component_sent[thisi]) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - component_sent[thisi] = TRUE; - } -#endif - } else if (cinfo->process == JPROC_PROGRESSIVE) { + if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that * seems wrong: the upper bound ought to depend on data precision. @@ -282,7 +462,7 @@ validate_script (j_compress_ptr cinfo) } /* Now verify that everything got sent. */ - if (cinfo->process == JPROC_PROGRESSIVE) { + if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED /* For progressive mode, we only check that at least some DC data * got sent for each component; the spec does not require that all bits @@ -302,7 +482,40 @@ validate_script (j_compress_ptr cinfo) } } -#endif /* NEED_SCAN_SCRIPT */ + +LOCAL(void) +reduce_script (j_compress_ptr cinfo) +/* Adapt scan script for use with reduced block size; + * assume that script has been validated before. + */ +{ + jpeg_scan_info * scanptr; + int idxout, idxin; + + /* Circumvent const declaration for this function */ + scanptr = (jpeg_scan_info *) cinfo->scan_info; + idxout = 0; + + for (idxin = 0; idxin < cinfo->num_scans; idxin++) { + /* After skipping, idxout becomes smaller than idxin */ + if (idxin != idxout) + /* Copy rest of data; + * note we stay in given chunk of allocated memory. + */ + scanptr[idxout] = scanptr[idxin]; + if (scanptr[idxout].Ss > cinfo->lim_Se) + /* Entire scan out of range - skip this entry */ + continue; + if (scanptr[idxout].Se > cinfo->lim_Se) + /* Limit scan to end of block */ + scanptr[idxout].Se = cinfo->lim_Se; + idxout++; + } + + cinfo->num_scans = idxout; +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ LOCAL(void) @@ -311,7 +524,7 @@ select_scan_parameters (j_compress_ptr cinfo) { int ci; -#ifdef NEED_SCAN_SCRIPT +#ifdef C_MULTISCAN_FILES_SUPPORTED if (cinfo->scan_info != NULL) { /* Prepare for current scan --- the script is already validated */ my_master_ptr master = (my_master_ptr) cinfo->master; @@ -322,11 +535,15 @@ select_scan_parameters (j_compress_ptr cinfo) cinfo->cur_comp_info[ci] = &cinfo->comp_info[scanptr->component_index[ci]]; } - cinfo->Ss = scanptr->Ss; - cinfo->Se = scanptr->Se; - cinfo->Ah = scanptr->Ah; - cinfo->Al = scanptr->Al; - } else + if (cinfo->progressive_mode) { + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + return; + } + } + else #endif { /* Prepare for single sequential-JPEG scan containing all components */ @@ -337,21 +554,11 @@ select_scan_parameters (j_compress_ptr cinfo) for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } - if (cinfo->lossless) { -#ifdef C_LOSSLESS_SUPPORTED - /* If we fall through to here, the user specified lossless, but did not - * provide a scan script. - */ - ERREXIT(cinfo, JERR_NO_LOSSLESS_SCRIPT); -#endif - } else { - cinfo->process = JPROC_SEQUENTIAL; - cinfo->Ss = 0; - cinfo->Se = DCTSIZE2-1; - cinfo->Ah = 0; - cinfo->Al = 0; - } } + cinfo->Ss = 0; + cinfo->Se = cinfo->block_size * cinfo->block_size - 1; + cinfo->Ah = 0; + cinfo->Al = 0; } @@ -362,74 +569,73 @@ per_scan_setup (j_compress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; - int data_unit = cinfo->data_unit; - + if (cinfo->comps_in_scan == 1) { - + /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; - + /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_data_units; - cinfo->MCU_rows_in_scan = compptr->height_in_data_units; - + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; - compptr->MCU_data_units = 1; - compptr->MCU_sample_width = data_unit; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_h_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. */ - tmp = (int) (compptr->height_in_data_units % compptr->v_samp_factor); + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; - + /* Prepare array describing MCU composition */ - cinfo->data_units_in_MCU = 1; + cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; - + } else { - + /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); - + /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*data_unit)); + jdiv_round_up((long) cinfo->jpeg_width, + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*data_unit)); - - cinfo->data_units_in_MCU = 0; - + jdiv_round_up((long) cinfo->jpeg_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + + cinfo->blocks_in_MCU = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * data_unit; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_data_units % compptr->MCU_width); + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_data_units % compptr->MCU_height); + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_data_units; - if (cinfo->data_units_in_MCU + mcublks > C_MAX_DATA_UNITS_IN_MCU) + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci; + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } - + } /* Convert restart specified in rows to actual MCU count. */ @@ -452,7 +658,6 @@ per_scan_setup (j_compress_ptr cinfo) METHODDEF(void) prepare_for_pass (j_compress_ptr cinfo) { -// j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; my_master_ptr master = (my_master_ptr) cinfo->master; switch (master->pass_type) { @@ -467,10 +672,11 @@ prepare_for_pass (j_compress_ptr cinfo) (*cinfo->downsample->start_pass) (cinfo); (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); } - (*cinfo->codec->entropy_start_pass) (cinfo, cinfo->optimize_coding); - (*cinfo->codec->start_pass) (cinfo, - (master->total_passes > 1 ? - JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->fdct->start_pass) (cinfo); + (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->coef->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); if (cinfo->optimize_coding) { /* No immediate data output; postpone writing frame/scan headers */ @@ -485,9 +691,9 @@ prepare_for_pass (j_compress_ptr cinfo) /* Do Huffman optimization for a scan after the first one. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); - if ((*cinfo->codec->need_optimization_pass) (cinfo) || cinfo->arith_code) { - (*cinfo->codec->entropy_start_pass) (cinfo, TRUE); - (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST); + if (cinfo->Ss != 0 || cinfo->Ah == 0) { + (*cinfo->entropy->start_pass) (cinfo, TRUE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); master->pub.call_pass_startup = FALSE; break; } @@ -505,8 +711,8 @@ prepare_for_pass (j_compress_ptr cinfo) select_scan_parameters(cinfo); per_scan_setup(cinfo); } - (*cinfo->codec->entropy_start_pass) (cinfo, FALSE); - (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->entropy->start_pass) (cinfo, FALSE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); /* We emit frame/scan headers now */ if (master->scan_number == 0) (*cinfo->marker->write_frame_header) (cinfo); @@ -554,13 +760,12 @@ pass_startup (j_compress_ptr cinfo) METHODDEF(void) finish_pass_master (j_compress_ptr cinfo) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; my_master_ptr master = (my_master_ptr) cinfo->master; /* The entropy coder always needs an end-of-pass call, * either to analyze statistics or to flush its output buffer. */ - (*lossyc->pub.entropy_finish_pass) (cinfo); + (*cinfo->entropy->finish_pass) (cinfo); /* Update state for next pass */ switch (master->pass_type) { @@ -600,32 +805,36 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_comp_master)); - cinfo->master = (struct jpeg_comp_master *) master; + cinfo->master = &master->pub; master->pub.prepare_for_pass = prepare_for_pass; master->pub.pass_startup = pass_startup; master->pub.finish_pass = finish_pass_master; master->pub.is_last_pass = FALSE; - cinfo->data_unit = cinfo->lossless ? 1 : DCTSIZE; - /* Validate parameters, determine derived values */ - initial_setup(cinfo); + initial_setup(cinfo, transcode_only); if (cinfo->scan_info != NULL) { -#ifdef NEED_SCAN_SCRIPT +#ifdef C_MULTISCAN_FILES_SUPPORTED validate_script(cinfo); + if (cinfo->block_size < DCTSIZE) + reduce_script(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - cinfo->process = JPROC_SEQUENTIAL; + cinfo->progressive_mode = FALSE; cinfo->num_scans = 1; } - if (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */ - cinfo->process == JPROC_LOSSLESS) - cinfo->optimize_coding = TRUE; /* assume default tables no good for - * progressive mode or lossless mode */ + if (cinfo->optimize_coding) + cinfo->arith_code = FALSE; /* disable arithmetic coding */ + else if (! cinfo->arith_code && + (cinfo->progressive_mode || + (cinfo->block_size > 1 && cinfo->block_size < DCTSIZE))) + /* TEMPORARY HACK ??? */ + /* assume default tables no good for progressive or reduced AC mode */ + cinfo->optimize_coding = TRUE; /* force Huffman optimization */ /* Initialize my private state */ if (transcode_only) { diff --git a/uppsrc/plugin/jpg/lib/jcodec.c b/uppsrc/plugin/jpg/lib/jcodec.c deleted file mode 100644 index 48b127e2e..000000000 --- a/uppsrc/plugin/jpg/lib/jcodec.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * jcodec.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains utility functions for the JPEG codec(s). - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossy.h" -#include "jlossls.h" - - -/* - * Initialize the compression codec. - * This is called only once, during master selection. - */ - -GLOBAL(void) -jinit_c_codec (j_compress_ptr cinfo) -{ - if (cinfo->process == JPROC_LOSSLESS) { -#ifdef C_LOSSLESS_SUPPORTED - jinit_lossless_c_codec(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_lossy_c_codec(cinfo); -} - - -/* - * Initialize the decompression codec. - * This is called only once, during master selection. - */ - -GLOBAL(void) -jinit_d_codec (j_decompress_ptr cinfo) -{ - if (cinfo->process == JPROC_LOSSLESS) { -#ifdef D_LOSSLESS_SUPPORTED - jinit_lossless_d_codec(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_lossy_d_codec(cinfo); -} diff --git a/uppsrc/plugin/jpg/lib/jconfig.h b/uppsrc/plugin/jpg/lib/jconfig.h index 648e36b44..a332b864c 100644 --- a/uppsrc/plugin/jpg/lib/jconfig.h +++ b/uppsrc/plugin/jpg/lib/jconfig.h @@ -1,5 +1,6 @@ -/* jconfig.h --- generated by ckconfig.c */ -/* see jconfig.doc for explanations */ +/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 9x or NT. */ +/* This file also works for Borland C++ 32-bit (bcc32) on Windows 9x or NT. */ +/* see jconfig.txt for explanations */ #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR @@ -11,19 +12,31 @@ #define HAVE_STDLIB_H #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H -#undef NEED_FAR_POINTERS +#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN +/* Define "boolean" as unsigned char, not enum, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +#ifndef boolean +typedef unsigned char boolean; +#endif +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ + + #ifdef JPEG_INTERNALS #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ -//#define JDCT_DEFAULT JDCT_FLOAT -//#define JDCT_FASTEST JDCT_FLOAT - #ifdef JPEG_CJPEG_DJPEG #define BMP_SUPPORTED /* BMP image file format */ @@ -32,9 +45,10 @@ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ -#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */ -#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ +#define TWO_FILE_COMMANDLINE /* optional */ +#define USE_SETMODE /* Microsoft has setmode() */ +#undef NEED_SIGNAL_CATCHER #undef DONT_USE_B_MODE -/* #define PROGRESS_REPORT */ /* optional */ +#undef PROGRESS_REPORT /* optional */ #endif /* JPEG_CJPEG_DJPEG */ diff --git a/uppsrc/plugin/jpg/lib/jcparam.c b/uppsrc/plugin/jpg/lib/jcparam.c index 033ff736b..1680e3925 100644 --- a/uppsrc/plugin/jpg/lib/jcparam.c +++ b/uppsrc/plugin/jpg/lib/jcparam.c @@ -2,6 +2,7 @@ * jcparam.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -60,6 +61,47 @@ jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, } +/* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ +static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; +static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + + +GLOBAL(void) +jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and straight percentage-scaling quality scales. + * This entry point allows different scalings for luminance and chrominance. + */ +{ + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + cinfo->q_scale_factor[0], force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + cinfo->q_scale_factor[1], force_baseline); +} + + GLOBAL(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) @@ -69,31 +111,6 @@ jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, * applications that insist on a linear percentage scaling. */ { - /* These are the sample quantization tables given in JPEG spec section K.1. - * The spec says that the values given produce "good" quality, and - * when divided by 2, "very good" quality. - */ - static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 - }; - static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 - }; - /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, scale_factor, force_baseline); @@ -133,7 +150,7 @@ jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables. * This is the standard quality-adjusting entry point for typical user * interfaces; only those who want detailed control over quantization tables - * would use the preceding three routines directly. + * would use the preceding routines directly. */ { /* Convert user 0-100 rating to percentage scaling */ @@ -187,12 +204,12 @@ std_huff_tables (j_compress_ptr cinfo) { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_luminance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - + static const UINT8 bits_dc_chrominance[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_chrominance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - + static const UINT8 bits_ac_luminance[17] = { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 val_ac_luminance[] = @@ -217,7 +234,7 @@ std_huff_tables (j_compress_ptr cinfo) 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; - + static const UINT8 bits_ac_chrominance[17] = { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 val_ac_chrominance[] = @@ -242,7 +259,7 @@ std_huff_tables (j_compress_ptr cinfo) 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; - + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], bits_dc_luminance, val_dc_luminance); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], @@ -284,7 +301,8 @@ jpeg_set_defaults (j_compress_ptr cinfo) /* Initialize everything not dependent on the color space */ - cinfo->lossless = FALSE; + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; cinfo->data_precision = BITS_IN_JSAMPLE; /* Set up two quantization tables using default quality of 75 */ jpeg_set_quality(cinfo, 75, TRUE); @@ -305,22 +323,24 @@ jpeg_set_defaults (j_compress_ptr cinfo) /* Expect normal source image, not raw downsampled data */ cinfo->raw_data_in = FALSE; - /* Use Huffman coding, not arithmetic coding, by default */ - cinfo->arith_code = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, use arithmetic coding. + * (Alternatively, using Huffman coding would be possible with forcing + * optimization on so that usable tables will be computed, or by + * supplying default tables that are valid for the desired precision.) + * Otherwise, use Huffman coding by default. + */ + cinfo->arith_code = cinfo->data_precision > 8 ? TRUE : FALSE; /* By default, don't do extra passes to optimize entropy coding */ cinfo->optimize_coding = FALSE; - /* The standard Huffman tables are only valid for 8-bit data precision. - * If the precision is higher, force optimization on so that usable - * tables will be computed. This test can be removed if default tables - * are supplied that are valid for the desired precision. - */ - if (cinfo->data_precision > 8) - cinfo->optimize_coding = TRUE; /* By default, use the simpler non-cosited sampling alignment */ cinfo->CCIR601_sampling = FALSE; + /* By default, apply fancy downsampling */ + cinfo->do_fancy_downsampling = TRUE; + /* No input smoothing */ cinfo->smoothing_factor = 0; @@ -339,6 +359,9 @@ jpeg_set_defaults (j_compress_ptr cinfo) * JFIF_minor_version to 2. We could probably get away with just defaulting * to 1.02, but there may still be some decoders in use that will complain * about that; saying 1.01 should minimize compatibility problems. + * + * For wide gamut colorspaces (BG_RGB and BG_YCC), the major version will be + * overridden by jpeg_set_colorspace and set to 2. */ cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ cinfo->JFIF_minor_version = 1; @@ -346,6 +369,9 @@ jpeg_set_defaults (j_compress_ptr cinfo) cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ cinfo->Y_density = 1; + /* No color transform */ + cinfo->color_transform = JCT_NONE; + /* Choose JPEG colorspace based on input space, set defaults accordingly */ jpeg_default_colorspace(cinfo); @@ -359,31 +385,34 @@ jpeg_set_defaults (j_compress_ptr cinfo) GLOBAL(void) jpeg_default_colorspace (j_compress_ptr cinfo) { - if (cinfo->lossless) - jpeg_set_colorspace(cinfo, cinfo->in_color_space); - else { /* lossy */ - switch (cinfo->in_color_space) { - case JCS_GRAYSCALE: - jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); - break; - case JCS_RGB: - jpeg_set_colorspace(cinfo, JCS_YCbCr); - break; - case JCS_YCbCr: - jpeg_set_colorspace(cinfo, JCS_YCbCr); - break; - case JCS_CMYK: - jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ - break; - case JCS_YCCK: - jpeg_set_colorspace(cinfo, JCS_YCCK); - break; - case JCS_UNKNOWN: - jpeg_set_colorspace(cinfo, JCS_UNKNOWN); - break; - default: - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - } + switch (cinfo->in_color_space) { + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_BG_RGB: + /* No translation for now -- conversion to BG_YCC not yet supportet */ + jpeg_set_colorspace(cinfo, JCS_BG_RGB); + break; + case JCS_BG_YCC: + jpeg_set_colorspace(cinfo, JCS_BG_YCC); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); } } @@ -421,33 +450,40 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ switch (colorspace) { + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; case JCS_GRAYSCALE: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 1; /* JFIF specifies component ID 1 */ - SET_COMP(0, 1, 1,1, 0, 0,0); + SET_COMP(0, 0x01, 1,1, 0, 0,0); break; case JCS_RGB: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ cinfo->num_components = 3; - SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); - SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); break; case JCS_YCbCr: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 3; /* JFIF specifies component IDs 1,2,3 */ - if (cinfo->lossless) { - SET_COMP(0, 1, 1,1, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - } else { /* lossy */ - /* We default to 2x2 subsamples of chrominance */ - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - } + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 0x01, 2,2, 0, 0,0); + SET_COMP(1, 0x02, 1,1, 1, 1,1); + SET_COMP(2, 0x03, 1,1, 1, 1,1); break; case JCS_CMYK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ @@ -460,26 +496,33 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) case JCS_YCCK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ cinfo->num_components = 4; - if (cinfo->lossless) { - SET_COMP(0, 1, 1,1, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - SET_COMP(3, 4, 1,1, 0, 0,0); - } else { /* lossy */ - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - SET_COMP(3, 4, 2,2, 0, 0,0); - } + SET_COMP(0, 0x01, 2,2, 0, 0,0); + SET_COMP(1, 0x02, 1,1, 1, 1,1); + SET_COMP(2, 0x03, 1,1, 1, 1,1); + SET_COMP(3, 0x04, 2,2, 0, 0,0); break; - case JCS_UNKNOWN: - cinfo->num_components = cinfo->input_components; - if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - for (ci = 0; ci < cinfo->num_components; ci++) { - SET_COMP(ci, ci, 1,1, 0, 0,0); - } + case JCS_BG_RGB: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->JFIF_major_version = 2; /* Set JFIF major version = 2 */ + cinfo->num_components = 3; + /* Add offset 0x20 to the normal R/G/B component IDs */ + SET_COMP(0, 0x72 /* 'r' */, 1,1, 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); + SET_COMP(1, 0x67 /* 'g' */, 1,1, 0, 0,0); + SET_COMP(2, 0x62 /* 'b' */, 1,1, 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); + break; + case JCS_BG_YCC: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->JFIF_major_version = 2; /* Set JFIF major version = 2 */ + cinfo->num_components = 3; + /* Add offset 0x20 to the normal Cb/Cr component IDs */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 0x01, 2,2, 0, 0,0); + SET_COMP(1, 0x22, 1,1, 1, 1,1); + SET_COMP(2, 0x23, 1,1, 1, 1,1); break; default: ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); @@ -489,6 +532,21 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) #ifdef C_PROGRESSIVE_SUPPORTED +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + LOCAL(jpeg_scan_info *) fill_scans (jpeg_scan_info * scanptr, int ncomps, int Ss, int Se, int Ah, int Al) @@ -508,22 +566,6 @@ fill_scans (jpeg_scan_info * scanptr, int ncomps, return scanptr; } - -LOCAL(jpeg_scan_info *) -fill_a_scan (jpeg_scan_info * scanptr, int ci, - int Ss, int Se, int Ah, int Al) -/* Support routine: generate one scan for specified component */ -{ - scanptr->comps_in_scan = 1; - scanptr->component_index[0] = ci; - scanptr->Ss = Ss; - scanptr->Se = Se; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; - return scanptr; -} - LOCAL(jpeg_scan_info *) fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) /* Support routine: generate interleaved DC scan if possible, else N scans */ @@ -564,8 +606,10 @@ jpeg_simple_progression (j_compress_ptr cinfo) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Figure space needed for script. Calculation must match code below! */ - if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ + if (ncomps == 3 && + (cinfo->jpeg_color_space == JCS_YCbCr || + cinfo->jpeg_color_space == JCS_BG_YCC)) { + /* Custom script for YCC color images. */ nscans = 10; } else { /* All-purpose script for other color spaces. */ @@ -580,7 +624,7 @@ jpeg_simple_progression (j_compress_ptr cinfo) * multiple compressions without changing the settings. To avoid a memory * leak if jpeg_simple_progression is called repeatedly for the same JPEG * object, we try to re-use previously allocated space, and we allocate - * enough space to handle YCbCr even if initially asked for grayscale. + * enough space to handle YCC even if initially asked for grayscale. */ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { cinfo->script_space_size = MAX(nscans, 10); @@ -592,8 +636,10 @@ jpeg_simple_progression (j_compress_ptr cinfo) cinfo->scan_info = scanptr; cinfo->num_scans = nscans; - if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ + if (ncomps == 3 && + (cinfo->jpeg_color_space == JCS_YCbCr || + cinfo->jpeg_color_space == JCS_BG_YCC)) { + /* Custom script for YCC color images. */ /* Initial DC scan */ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); /* Initial AC scan: get some luma data out in a hurry */ @@ -627,61 +673,3 @@ jpeg_simple_progression (j_compress_ptr cinfo) } #endif /* C_PROGRESSIVE_SUPPORTED */ - - -#ifdef C_LOSSLESS_SUPPORTED - -/* - * Create a single-entry lossless-JPEG script containing all components. - * cinfo->num_components must be correct. - */ - -GLOBAL(void) -jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform) -{ - int ncomps = cinfo->num_components; - int nscans = 1; - int ci; - jpeg_scan_info * scanptr; - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - cinfo->lossless = TRUE; - - /* Set jpeg_color_space. */ - jpeg_default_colorspace(cinfo); - - /* Check to ensure that all components will fit in one scan. */ - if (cinfo->num_components > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPS_IN_SCAN); - - /* Allocate space for script. - * We need to put it in the permanent pool in case the application performs - * multiple compressions without changing the settings. To avoid a memory - * leak if jpeg_simple_lossless is called repeatedly for the same JPEG - * object, we try to re-use previously allocated space. - */ - if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { - cinfo->script_space_size = nscans; - cinfo->script_space = (jpeg_scan_info *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - cinfo->script_space_size * SIZEOF(jpeg_scan_info)); - } - scanptr = cinfo->script_space; - cinfo->scan_info = scanptr; - cinfo->num_scans = nscans; - - /* Fill the script. */ - scanptr->comps_in_scan = ncomps; - for (ci = 0; ci < ncomps; ci++) - scanptr->component_index[ci] = ci; - scanptr->Ss = predictor; - scanptr->Se = 0; - scanptr->Ah = 0; - scanptr->Al = point_transform; -} - -#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jcphuff.c b/uppsrc/plugin/jpg/lib/jcphuff.c deleted file mode 100644 index 779640307..000000000 --- a/uppsrc/plugin/jpg/lib/jcphuff.c +++ /dev/null @@ -1,848 +0,0 @@ -/* - * jcphuff.c - * - * Copyright (C) 1995-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy encoding routines for progressive JPEG. - * - * We do not support output suspension in this module, since the library - * currently does not allow multiple-scan files to be written with output - * suspension. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy codec */ -#include "jchuff.h" /* Declarations shared with jc*huff.c */ - -#ifdef C_PROGRESSIVE_SUPPORTED - -/* Expanded entropy encoder object for progressive Huffman encoding. */ - -typedef struct { - /* Mode flag: TRUE for optimization, FALSE for actual data output */ - boolean gather_statistics; - - /* Bit-level coding status. - * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. - */ - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ - j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ - - /* Coding status for DC components */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ - - /* Coding status for AC components */ - int ac_tbl_no; /* the table number of the single component */ - unsigned int EOBRUN; /* run length of EOBs */ - unsigned int BE; /* # of buffered correction bits before MCU */ - char * bit_buffer; /* buffer for correction bits (1 per char) */ - /* packing correction bits tightly would save some space but cost time... */ - - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ - - /* Pointers to derived tables (these workspaces have image lifespan). - * Since any one scan codes only DC or only AC, we only need one set - * of tables, not one for DC and one for AC. - */ - c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - /* Statistics tables for optimization; again, one set is enough */ - long * count_ptrs[NUM_HUFF_TBLS]; -} phuff_entropy_encoder; - -typedef phuff_entropy_encoder * phuff_entropy_ptr; - -/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit - * buffer can hold. Larger sizes may slightly improve compression, but - * 1000 is already well into the realm of overkill. - * The minimum safe size is 64 bits. - */ - -#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ - -/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. - * We assume that int right shift is unsigned if INT32 right shift is, - * which should be safe. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS int ishift_temp; -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -/* Forward declarations */ -METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); -METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); - - -/* - * Initialize for a Huffman-compressed scan using progressive JPEG. - */ - -METHODDEF(void) -start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; - boolean is_DC_band; - int ci, tbl; - jpeg_component_info * compptr; - - entropy->cinfo = cinfo; - entropy->gather_statistics = gather_statistics; - - is_DC_band = (cinfo->Ss == 0); - - /* We assume jcmaster.c already validated the scan parameters. */ - - /* Select execution routines */ - if (cinfo->Ah == 0) { - if (is_DC_band) - lossyc->entropy_encode_mcu = encode_mcu_DC_first; - else - lossyc->entropy_encode_mcu = encode_mcu_AC_first; - } else { - if (is_DC_band) - lossyc->entropy_encode_mcu = encode_mcu_DC_refine; - else { - lossyc->entropy_encode_mcu = encode_mcu_AC_refine; - /* AC refinement needs a correction bit buffer */ - if (entropy->bit_buffer == NULL) - entropy->bit_buffer = (char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - MAX_CORR_BITS * SIZEOF(char)); - } - } - if (gather_statistics) - lossyc->pub.entropy_finish_pass = finish_pass_gather_phuff; - else - lossyc->pub.entropy_finish_pass = finish_pass_phuff; - - /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 - * for AC coefficients. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Initialize DC predictions to 0 */ - entropy->last_dc_val[ci] = 0; - /* Get table index */ - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ - continue; - tbl = compptr->dc_tbl_no; - } else { - entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; - } - if (gather_statistics) { - /* Check for invalid table index */ - /* (make_c_derived_tbl does this in the other path) */ - if (tbl < 0 || tbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->count_ptrs[tbl] == NULL) - entropy->count_ptrs[tbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); - } else { - /* Compute derived values for Huffman table */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, - & entropy->derived_tbls[tbl]); - } - } - - /* Initialize AC stuff */ - entropy->EOBRUN = 0; - entropy->BE = 0; - - /* Initialize bit buffer to empty */ - entropy->put_buffer = 0; - entropy->put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} - - -/* Outputting bytes to the file. - * NB: these must be called only when actually outputting, - * that is, entropy->gather_statistics == FALSE. - */ - -/* Emit a byte */ -#define emit_byte(entropy,val) \ - { *(entropy)->next_output_byte++ = (JOCTET) (val); \ - if (--(entropy)->free_in_buffer == 0) \ - dump_buffer(entropy); } - - -LOCAL(void) -dump_buffer (phuff_entropy_ptr entropy) -/* Empty the output buffer; we do not support suspension in this module. */ -{ - struct jpeg_destination_mgr * dest = entropy->cinfo->dest; - - if (! (*dest->empty_output_buffer) (entropy->cinfo)) - ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); - /* After a successful buffer dump, must reset buffer pointers */ - entropy->next_output_byte = dest->next_output_byte; - entropy->free_in_buffer = dest->free_in_buffer; -} - - -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - -INLINE -LOCAL(void) -emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) -/* Emit some bits, unless we are in gather mode */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = entropy->put_bits; - - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - - if (entropy->gather_statistics) - return; /* do nothing if we're only getting stats */ - - put_buffer &= (((INT32) 1)<put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(entropy, c); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(entropy, 0); - } - put_buffer <<= 8; - put_bits -= 8; - } - - entropy->put_buffer = put_buffer; /* update variables */ - entropy->put_bits = put_bits; -} - - -LOCAL(void) -flush_bits (phuff_entropy_ptr entropy) -{ - emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ - entropy->put_buffer = 0; /* and reset bit-buffer to empty */ - entropy->put_bits = 0; -} - - -/* - * Emit (or just count) a Huffman symbol. - */ - -INLINE -LOCAL(void) -emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) -{ - if (entropy->gather_statistics) - entropy->count_ptrs[tbl_no][symbol]++; - else { - c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; - emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); - } -} - - -/* - * Emit bits from a correction bit buffer. - */ - -LOCAL(void) -emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, - unsigned int nbits) -{ - if (entropy->gather_statistics) - return; /* no real work */ - - while (nbits > 0) { - emit_bits(entropy, (unsigned int) (*bufstart), 1); - bufstart++; - nbits--; - } -} - - -/* - * Emit any pending EOBRUN symbol. - */ - -LOCAL(void) -emit_eobrun (phuff_entropy_ptr entropy) -{ - register int temp, nbits; - - if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ - temp = entropy->EOBRUN; - nbits = 0; - while ((temp >>= 1)) - nbits++; - /* safety check: shouldn't happen given limited correction-bit buffer */ - if (nbits > 14) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - - emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); - if (nbits) - emit_bits(entropy, entropy->EOBRUN, nbits); - - entropy->EOBRUN = 0; - - /* Emit any buffered correction bits */ - emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); - entropy->BE = 0; - } -} - - -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(void) -emit_restart (phuff_entropy_ptr entropy, int restart_num) -{ - int ci; - - emit_eobrun(entropy); - - if (! entropy->gather_statistics) { - flush_bits(entropy); - emit_byte(entropy, 0xFF); - emit_byte(entropy, JPEG_RST0 + restart_num); - } - - if (entropy->cinfo->Ss == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) - entropy->last_dc_val[ci] = 0; - } else { - /* Re-initialize all AC-related fields to 0 */ - entropy->EOBRUN = 0; - entropy->BE = 0; - } -} - - -/* - * MCU encoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; - register int temp, temp2; - register int nbits; - int blkn, ci; - int Al = cinfo->Al; - JBLOCKROW block; - jpeg_component_info * compptr; - ISHIFT_TEMPS - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - - /* Compute the DC value after the required point transform by Al. - * This is simply an arithmetic right shift. - */ - temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); - - /* DC differences are figured on the point-transformed values. */ - temp = temp2 - entropy->last_dc_val[ci]; - entropy->last_dc_val[ci] = temp2; - - /* Encode the DC coefficient difference per section G.1.2.1 */ - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count/emit the Huffman-coded symbol for the number of bits */ - emit_symbol(entropy, compptr->dc_tbl_no, nbits); - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits) /* emit_bits rejects calls with size 0 */ - emit_bits(entropy, (unsigned int) temp2, nbits); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; - register int temp, temp2; - register int nbits; - register int r, k; - int Se = cinfo->Se; - int Al = cinfo->Al; - JBLOCKROW block; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data block */ - block = MCU_data[0]; - - /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ - - r = 0; /* r = run length of zeros */ - - for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { - r++; - continue; - } - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value; so the code is - * interwoven with finding the abs value (temp) and output bits (temp2). - */ - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ - temp2 = ~temp; - } else { - temp >>= Al; /* apply the point transform */ - temp2 = temp; - } - /* Watch out for case that nonzero coef is zero after point transform */ - if (temp == 0) { - r++; - continue; - } - - /* Emit any pending EOBRUN */ - if (entropy->EOBRUN > 0) - emit_eobrun(entropy); - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - emit_bits(entropy, (unsigned int) temp2, nbits); - - r = 0; /* reset zero run length */ - } - - if (r > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - if (entropy->EOBRUN == 0x7FFF) - emit_eobrun(entropy); /* force it out to avoid overflow */ - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - -METHODDEF(boolean) -encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; - register int temp; - int blkn; - int Al = cinfo->Al; - JBLOCKROW block; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { - block = MCU_data[blkn]; - - /* We simply emit the Al'th bit of the DC coefficient value. */ - temp = (*block)[0]; - emit_bits(entropy, (unsigned int) (temp >> Al), 1); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; - register int temp; - register int r, k; - int EOB; - char *BR_buffer; - unsigned int BR; - int Se = cinfo->Se; - int Al = cinfo->Al; - JBLOCKROW block; - int absvalues[DCTSIZE2]; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data block */ - block = MCU_data[0]; - - /* It is convenient to make a pre-pass to determine the transformed - * coefficients' absolute values and the EOB position. - */ - EOB = 0; - for (k = cinfo->Ss; k <= Se; k++) { - temp = (*block)[jpeg_natural_order[k]]; - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value. - */ - if (temp < 0) - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - absvalues[k] = temp; /* save abs value for main pass */ - if (temp == 1) - EOB = k; /* EOB = index of last newly-nonzero coef */ - } - - /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ - - r = 0; /* r = run length of zeros */ - BR = 0; /* BR = count of buffered bits added now */ - BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ - - for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = absvalues[k]) == 0) { - r++; - continue; - } - - /* Emit any required ZRLs, but not if they can be folded into EOB */ - while (r > 15 && k <= EOB) { - /* emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - /* Emit ZRL */ - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - /* Emit buffered correction bits that must be associated with ZRL */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - } - - /* If the coef was previously nonzero, it only needs a correction bit. - * NOTE: a straight translation of the spec's figure G.7 would suggest - * that we also need to test r > 15. But if r > 15, we can only get here - * if k > EOB, which implies that this coefficient is not 1. - */ - if (temp > 1) { - /* The correction bit is the next bit of the absolute value. */ - BR_buffer[BR++] = (char) (temp & 1); - continue; - } - - /* Emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); - - /* Emit output bit for newly-nonzero coef */ - temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; - emit_bits(entropy, (unsigned int) temp, 1); - - /* Emit buffered correction bits that must be associated with this code */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - r = 0; /* reset zero run length */ - } - - if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - entropy->BE += BR; /* concat my correction bits to older ones */ - /* We force out the EOB if we risk either: - * 1. overflow of the EOB counter; - * 2. overflow of the correction bit buffer during the next MCU. - */ - if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) - emit_eobrun(entropy); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * Finish up at the end of a Huffman-compressed progressive scan. - */ - -METHODDEF(void) -finish_pass_phuff (j_compress_ptr cinfo) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Flush out any buffered data */ - emit_eobrun(entropy); - flush_bits(entropy); - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; -} - - -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - -METHODDEF(void) -finish_pass_gather_phuff (j_compress_ptr cinfo) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; - boolean is_DC_band; - int ci, tbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did[NUM_HUFF_TBLS]; - - /* Flush out buffered data (all we care about is counting the EOB symbol) */ - emit_eobrun(entropy); - - is_DC_band = (cinfo->Ss == 0); - - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ - MEMZERO(did, SIZEOF(did)); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ - continue; - tbl = compptr->dc_tbl_no; - } else { - tbl = compptr->ac_tbl_no; - } - if (! did[tbl]) { - if (is_DC_band) - htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; - else - htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); - did[tbl] = TRUE; - } - } -} - - -METHODDEF(boolean) -need_optimization_pass (j_compress_ptr cinfo) -{ - return (cinfo->Ss != 0 || cinfo->Ah == 0); -} - - -/* - * Module initialization routine for progressive Huffman entropy encoding. - */ - -GLOBAL(void) -jinit_phuff_encoder (j_compress_ptr cinfo) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - phuff_entropy_ptr entropy; - int i; - - entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(phuff_entropy_encoder)); - lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy; - lossyc->pub.entropy_start_pass = start_pass_phuff; - lossyc->pub.need_optimization_pass = need_optimization_pass; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - entropy->count_ptrs[i] = NULL; - } - entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ -} - -#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jcpred.c b/uppsrc/plugin/jpg/lib/jcpred.c deleted file mode 100644 index 75f70c745..000000000 --- a/uppsrc/plugin/jpg/lib/jcpred.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * jcpred.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains sample differencing for lossless JPEG. - * - * In order to avoid paying the performance penalty of having to check the - * predictor being used and the row being processed for each call of the - * undifferencer, and to promote optimization, we have separate differencing - * functions for each case. - * - * We are able to avoid duplicating source code by implementing the predictors - * and differencers as macros. Each of the differencing functions are - * simply wrappers around a DIFFERENCE macro with the appropriate PREDICTOR - * macro passed as an argument. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" /* Private declarations for lossless codec */ - - -#ifdef C_LOSSLESS_SUPPORTED - -/* Private predictor object */ - -typedef struct { - /* MCU-rows left in the restart interval for each component */ - unsigned int restart_rows_to_go[MAX_COMPONENTS]; -} c_predictor; - -typedef c_predictor * c_pred_ptr; - -/* Forward declarations */ -LOCAL(void) reset_predictor - JPP((j_compress_ptr cinfo, int ci)); -METHODDEF(void) start_pass - JPP((j_compress_ptr cinfo)); - - -/* Predictor for the first column of the first row: 2^(P-Pt-1) */ -#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) - -/* Predictor for the first column of the remaining rows: Rb */ -#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0]) - - -/* - * 1-Dimensional differencer routine. - * - * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR - * is used as the special case predictor for the first column, which must be - * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples - * use PREDICTOR1. - */ - -#define DIFFERENCE_1D(INITIAL_PREDICTOR) \ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \ - c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \ - boolean restart = FALSE; \ - unsigned xindex; \ - int samp, Ra; \ - \ - samp = GETJSAMPLE(input_buf[0]); \ - diff_buf[0] = samp - INITIAL_PREDICTOR; \ - \ - for (xindex = 1; xindex < width; xindex++) { \ - Ra = samp; \ - samp = GETJSAMPLE(input_buf[xindex]); \ - diff_buf[xindex] = samp - PREDICTOR1; \ - } \ - \ - /* Account for restart interval (no-op if not using restarts) */ \ - if (cinfo->restart_interval) { \ - if (--(pred->restart_rows_to_go[ci]) == 0) { \ - reset_predictor(cinfo, ci); \ - restart = TRUE; \ - } \ - } \ - (void)restart; - - -/* - * 2-Dimensional differencer routine. - * - * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is - * used as the special case predictor for the first column. The remaining - * samples use PREDICTOR, which is a function of Ra, Rb, Rc. - * - * Because prev_row and output_buf may point to the same storage area (in an - * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc - * before writing the current reconstructed sample value into output_buf. - */ - -#define DIFFERENCE_2D(PREDICTOR) \ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \ - c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \ - unsigned xindex; \ - int samp, Ra, Rb, Rc; \ - \ - Rb = GETJSAMPLE(prev_row[0]); \ - samp = GETJSAMPLE(input_buf[0]); \ - diff_buf[0] = samp - PREDICTOR2; \ - \ - for (xindex = 1; xindex < width; xindex++) { \ - Rc = Rb; \ - Rb = GETJSAMPLE(prev_row[xindex]); \ - Ra = samp; \ - samp = GETJSAMPLE(input_buf[xindex]); \ - diff_buf[xindex] = samp - PREDICTOR; \ - } \ - \ - /* Account for restart interval (no-op if not using restarts) */ \ - if (cinfo->restart_interval) { \ - if (--pred->restart_rows_to_go[ci] == 0) \ - reset_predictor(cinfo, ci); \ - } \ - (void)Rc;(void)Ra; - - -/* - * Differencers for the all rows but the first in a scan or restart interval. - * The first sample in the row is differenced using the vertical - * predictor (2). The rest of the samples are differenced using the - * predictor specified in the scan header. - */ - -METHODDEF(void) -jpeg_difference1(j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width) -{ - DIFFERENCE_1D(INITIAL_PREDICTOR2); -} - -METHODDEF(void) -jpeg_difference2(j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width) -{ - DIFFERENCE_2D(PREDICTOR2); -} - -METHODDEF(void) -jpeg_difference3(j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width) -{ - DIFFERENCE_2D(PREDICTOR3); -} - -METHODDEF(void) -jpeg_difference4(j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width) -{ - DIFFERENCE_2D(PREDICTOR4); -} - -METHODDEF(void) -jpeg_difference5(j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width) -{ - DIFFERENCE_2D(PREDICTOR5); -} - -METHODDEF(void) -jpeg_difference6(j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width) -{ - DIFFERENCE_2D(PREDICTOR6); -} - -METHODDEF(void) -jpeg_difference7(j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width) -{ - DIFFERENCE_2D(PREDICTOR7); -} - - -/* - * Differencer for the first row in a scan or restart interval. The first - * sample in the row is differenced using the special predictor constant - * x=2^(P-Pt-1). The rest of the samples are differenced using the - * 1-D horizontal predictor (1). - */ - -METHODDEF(void) -jpeg_difference_first_row(j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width) -{ - DIFFERENCE_1D(INITIAL_PREDICTORx); - - /* - * Now that we have differenced the first row, we want to use the - * differencer which corresponds to the predictor specified in the - * scan header. - * - * Note that we don't to do this if we have just reset the predictor - * for a new restart interval. - */ - if (!restart) { - switch (cinfo->Ss) { - case 1: - losslsc->predict_difference[ci] = jpeg_difference1; - break; - case 2: - losslsc->predict_difference[ci] = jpeg_difference2; - break; - case 3: - losslsc->predict_difference[ci] = jpeg_difference3; - break; - case 4: - losslsc->predict_difference[ci] = jpeg_difference4; - break; - case 5: - losslsc->predict_difference[ci] = jpeg_difference5; - break; - case 6: - losslsc->predict_difference[ci] = jpeg_difference6; - break; - case 7: - losslsc->predict_difference[ci] = jpeg_difference7; - break; - } - } -} - -/* - * Reset predictor at the start of a pass or restart interval. - */ - -LOCAL(void) -reset_predictor (j_compress_ptr cinfo, int ci) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; - - /* Initialize restart counter */ - pred->restart_rows_to_go[ci] = - cinfo->restart_interval / cinfo->MCUs_per_row; - - /* Set difference function to first row function */ - losslsc->predict_difference[ci] = jpeg_difference_first_row; -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF(void) -start_pass (j_compress_ptr cinfo) -{ -// j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; -// c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; - int ci; - - /* Check that the restart interval is an integer multiple of the number - * of MCU in an MCU-row. - */ - if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) - ERREXIT2(cinfo, JERR_BAD_RESTART, - cinfo->restart_interval, cinfo->MCUs_per_row); - - /* Set predictors for start of pass */ - for (ci = 0; ci < cinfo->num_components; ci++) - reset_predictor(cinfo, ci); -} - - -/* - * Module initialization routine for the differencer. - */ - -GLOBAL(void) -jinit_differencer (j_compress_ptr cinfo) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - c_pred_ptr pred; - - pred = (c_pred_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(c_predictor)); - losslsc->pred_private = (void *) pred; - losslsc->predict_start_pass = start_pass; -} - -#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jcprepct.c b/uppsrc/plugin/jpg/lib/jcprepct.c index 88f454abf..00101e0b5 100644 --- a/uppsrc/plugin/jpg/lib/jcprepct.c +++ b/uppsrc/plugin/jpg/lib/jcprepct.c @@ -1,7 +1,7 @@ /* * jcprepct.c * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -173,10 +173,12 @@ pre_process_data (j_compress_ptr cinfo, *out_row_group_ctr < out_row_groups_avail) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { + numrows = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; expand_bottom_edge(output_buf[ci], - compptr->width_in_data_units * cinfo->data_unit, - (int) (*out_row_group_ctr * compptr->v_samp_factor), - (int) (out_row_groups_avail * compptr->v_samp_factor)); + compptr->width_in_blocks * compptr->DCT_h_scaled_size, + (int) (*out_row_group_ctr * numrows), + (int) (out_row_groups_avail * numrows)); } *out_row_group_ctr = out_row_groups_avail; break; /* can exit outer loop without test */ @@ -288,7 +290,8 @@ create_context_buffer (j_compress_ptr cinfo) */ true_buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit * + (JDIMENSION) (((long) compptr->width_in_blocks * + cinfo->min_DCT_h_scaled_size * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) (3 * rgroup_height)); /* Copy true buffer row pointers into the middle of the fake row array */ @@ -346,7 +349,8 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) ci++, compptr++) { prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit * + (JDIMENSION) (((long) compptr->width_in_blocks * + cinfo->min_DCT_h_scaled_size * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); } diff --git a/uppsrc/plugin/jpg/lib/jcsample.c b/uppsrc/plugin/jpg/lib/jcsample.c index dbc26c8ea..1aef8a6fc 100644 --- a/uppsrc/plugin/jpg/lib/jcsample.c +++ b/uppsrc/plugin/jpg/lib/jcsample.c @@ -1,7 +1,7 @@ /* * jcsample.c * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -62,6 +62,15 @@ typedef struct { /* Downsampling method pointers, one per component */ downsample1_ptr methods[MAX_COMPONENTS]; + + /* Height of an output row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_downsample need not + * recompute them each time. They are unused for other downsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; } my_downsampler; typedef my_downsampler * my_downsample_ptr; @@ -123,7 +132,8 @@ sep_downsample (j_compress_ptr cinfo, for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { in_ptr = input_buf[ci] + in_row_index; - out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); + out_ptr = output_buf[ci] + + (out_row_group_index * downsample->rowgroup_height[ci]); (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); } } @@ -140,14 +150,15 @@ METHODDEF(void) int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ - JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; JSAMPROW inptr, outptr; INT32 outvalue; - h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; - v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + h_expand = downsample->h_expand[compptr->component_index]; + v_expand = downsample->v_expand[compptr->component_index]; numpix = h_expand * v_expand; numpix2 = numpix/2; @@ -158,8 +169,8 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * h_expand); - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; for (outcol = 0, outcol_h = 0; outcol < output_cols; outcol++, outcol_h += h_expand) { @@ -173,6 +184,7 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); } inrow += v_expand; + outrow++; } } @@ -191,8 +203,8 @@ fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor, cinfo->image_width); /* Edge-expand */ - expand_right_edge(output_data, cinfo->max_v_samp_factor, - cinfo->image_width, compptr->width_in_data_units * cinfo->data_unit); + expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, + compptr->width_in_blocks * compptr->DCT_h_scaled_size); } @@ -212,9 +224,9 @@ METHODDEF(void) h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { - int outrow; + int inrow; JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr, outptr; register int bias; @@ -225,9 +237,9 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + outptr = output_data[inrow]; + inptr = input_data[inrow]; bias = 0; /* bias = 0,1,0,1,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) @@ -251,7 +263,7 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, { int inrow, outrow; JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr0, inptr1, outptr; register int bias; @@ -262,8 +274,8 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; @@ -276,6 +288,7 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, inptr0 += 2; inptr1 += 2; } inrow += 2; + outrow++; } } @@ -294,7 +307,7 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, { int inrow, outrow; JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; @@ -321,8 +334,8 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; @@ -378,6 +391,7 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, *outptr = (JSAMPLE) ((membersum + 32768) >> 16); inrow += 2; + outrow++; } } @@ -392,9 +406,9 @@ METHODDEF(void) fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { - int outrow; + int inrow; JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; @@ -415,11 +429,11 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; - above_ptr = input_data[outrow-1]; - below_ptr = input_data[outrow+1]; + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + outptr = output_data[inrow]; + inptr = input_data[inrow]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+1]; /* Special case for first column */ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + @@ -467,6 +481,7 @@ jinit_downsampler (j_compress_ptr cinfo) int ci; jpeg_component_info * compptr; boolean smoothok = TRUE; + int h_in_group, v_in_group, h_out_group, v_out_group; downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, @@ -482,8 +497,17 @@ jinit_downsampler (j_compress_ptr cinfo) /* Verify we can handle the sampling factors, and set up method pointers */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - if (compptr->h_samp_factor == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { + /* Compute size of an "output group" for DCT scaling. This many samples + * are to be converted from max_h_samp_factor * max_v_samp_factor pixels. + */ + h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / + cinfo->min_DCT_h_scaled_size; + v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; + h_in_group = cinfo->max_h_samp_factor; + v_in_group = cinfo->max_v_samp_factor; + downsample->rowgroup_height[ci] = v_out_group; /* save for use later */ + if (h_in_group == h_out_group && v_in_group == v_out_group) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = fullsize_smooth_downsample; @@ -491,12 +515,12 @@ jinit_downsampler (j_compress_ptr cinfo) } else #endif downsample->methods[ci] = fullsize_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { + } else if (h_in_group == h_out_group * 2 && + v_in_group == v_out_group) { smoothok = FALSE; downsample->methods[ci] = h2v1_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { + } else if (h_in_group == h_out_group * 2 && + v_in_group == v_out_group * 2) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = h2v2_smooth_downsample; @@ -504,10 +528,12 @@ jinit_downsampler (j_compress_ptr cinfo) } else #endif downsample->methods[ci] = h2v2_downsample; - } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && - (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + } else if ((h_in_group % h_out_group) == 0 && + (v_in_group % v_out_group) == 0) { smoothok = FALSE; downsample->methods[ci] = int_downsample; + downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group); + downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); } diff --git a/uppsrc/plugin/jpg/lib/jcscale.c b/uppsrc/plugin/jpg/lib/jcscale.c deleted file mode 100644 index 051388bb7..000000000 --- a/uppsrc/plugin/jpg/lib/jcscale.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * jcscale.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains sample downscaling by 2^Pt for lossless JPEG. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" /* Private declarations for lossless codec */ - - -#ifdef C_LOSSLESS_SUPPORTED - -METHODDEF(void) -simple_downscale(j_compress_ptr cinfo, - JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width) -{ -// j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - unsigned xindex; - - for (xindex = 0; xindex < width; xindex++) - output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(GETJSAMPLE(input_buf[xindex]), - cinfo->Al); -} - - -METHODDEF(void) -noscale(j_compress_ptr cinfo, - JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width) -{ - MEMCOPY(output_buf, input_buf, width * SIZEOF(JSAMPLE)); - return; -} - - -METHODDEF(void) -scaler_start_pass (j_compress_ptr cinfo) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - - /* Set scaler function based on Pt */ - if (cinfo->Al) - losslsc->scaler_scale = simple_downscale; - else - losslsc->scaler_scale = noscale; -} - - -GLOBAL(void) -jinit_c_scaler (j_compress_ptr cinfo) -{ - j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; - - losslsc->scaler_start_pass = scaler_start_pass; -} - -#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jcshuff.c b/uppsrc/plugin/jpg/lib/jcshuff.c deleted file mode 100644 index 7dc059a3e..000000000 --- a/uppsrc/plugin/jpg/lib/jcshuff.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * jcshuff.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy encoding routines for sequential JPEG. - * - * Much of the complexity here has to do with supporting output suspension. - * If the data destination module demands suspension, we want to be able to - * back up to the start of the current MCU. To do this, we copy state - * variables into local working storage, and update them back to the - * permanent JPEG objects only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy codec */ -#include "jchuff.h" /* Declarations shared with jc*huff.c */ - - -/* Expanded entropy encoder object for Huffman encoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).put_buffer = (src).put_buffer, \ - (dest).put_bits = (src).put_bits, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - savable_state saved; /* Bit buffer & DC state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; - -#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ - long * dc_count_ptrs[NUM_HUFF_TBLS]; - long * ac_count_ptrs[NUM_HUFF_TBLS]; -#endif -} shuff_entropy_encoder; - -typedef shuff_entropy_encoder * shuff_entropy_ptr; - -/* Working state while writing an MCU. - * This struct contains all the fields that are needed by subroutines. - */ - -typedef struct { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - savable_state cur; /* Current bit buffer & DC state */ - j_compress_ptr cinfo; /* dump_buffer needs access to this */ -} working_state; - - -/* Forward declarations */ -METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); -#ifdef ENTROPY_OPT_SUPPORTED -METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); -#endif - - -/* - * Initialize for a Huffman-compressed scan. - * If gather_statistics is TRUE, we do not output anything during the scan, - * just count the Huffman symbols used and generate Huffman code tables. - */ - -METHODDEF(void) -start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; - int ci, dctbl, actbl; - jpeg_component_info * compptr; - - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - lossyc->entropy_encode_mcu = encode_mcu_gather; - lossyc->pub.entropy_finish_pass = finish_pass_gather; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - lossyc->entropy_encode_mcu = encode_mcu_huff; - lossyc->pub.entropy_finish_pass = finish_pass_huff; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - /* Check for invalid table indexes */ - /* (make_c_derived_tbl does this in the other path) */ - if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); - if (actbl < 0 || actbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->dc_count_ptrs[dctbl] == NULL) - entropy->dc_count_ptrs[dctbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); - if (entropy->ac_count_ptrs[actbl] == NULL) - entropy->ac_count_ptrs[actbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); -#endif - } else { - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bit buffer to empty */ - entropy->saved.put_buffer = 0; - entropy->saved.put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} - - -/* Outputting bytes to the file */ - -/* Emit a byte, taking 'action' if must suspend. */ -#define emit_byte(state,val,action) \ - { *(state)->next_output_byte++ = (JOCTET) (val); \ - if (--(state)->free_in_buffer == 0) \ - if (! dump_buffer(state)) \ - { action; } } - - -LOCAL(boolean) -dump_buffer (working_state * state) -/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ -{ - struct jpeg_destination_mgr * dest = state->cinfo->dest; - - if (! (*dest->empty_output_buffer) (state->cinfo)) - return FALSE; - /* After a successful buffer dump, must reset buffer pointers */ - state->next_output_byte = dest->next_output_byte; - state->free_in_buffer = dest->free_in_buffer; - return TRUE; -} - - -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - -INLINE -LOCAL(boolean) -emit_bits (working_state * state, unsigned int code, int size) -/* Emit some bits; return TRUE if successful, FALSE if must suspend */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = state->cur.put_bits; - - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); - - put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(state, c, return FALSE); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(state, 0, return FALSE); - } - put_buffer <<= 8; - put_bits -= 8; - } - - state->cur.put_buffer = put_buffer; /* update state variables */ - state->cur.put_bits = put_bits; - - return TRUE; -} - - -LOCAL(boolean) -flush_bits (working_state * state) -{ - if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ - return FALSE; - state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ - state->cur.put_bits = 0; - return TRUE; -} - - -/* Encode a single block's worth of coefficients */ - -LOCAL(boolean) -encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, - c_derived_tbl *dctbl, c_derived_tbl *actbl) -{ - register int temp, temp2; - register int nbits; - register int k, r, i; - - /* Encode the DC coefficient difference per section F.1.2.1 */ - - temp = temp2 = block[0] - last_dc_val; - - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - - /* Emit the Huffman-coded symbol for the number of bits */ - if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) - return FALSE; - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits) /* emit_bits rejects calls with size 0 */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) - return FALSE; - - /* Encode the AC coefficients per section F.1.2.2 */ - - r = 0; /* r = run length of zeros */ - - for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { - r++; - } else { - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) - return FALSE; - r -= 16; - } - - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - - /* Emit Huffman symbol for run length / number of bits */ - i = (r << 4) + nbits; - if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) - return FALSE; - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) - return FALSE; - - r = 0; - } - } - - /* If the last coef(s) were zero, emit an end-of-block code */ - if (r > 0) - if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) - return FALSE; - - return TRUE; -} - - -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(boolean) -emit_restart (working_state * state, int restart_num) -{ - int ci; - - if (! flush_bits(state)) - return FALSE; - - emit_byte(state, 0xFF, return FALSE); - emit_byte(state, JPEG_RST0 + restart_num, return FALSE); - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) - state->cur.last_dc_val[ci] = 0; - - /* The restart counter is not updated until we successfully write the MCU. */ - - return TRUE; -} - - -/* - * Encode and output one MCU's worth of Huffman-compressed coefficients. - */ - -METHODDEF(boolean) -encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; - working_state state; - int blkn, ci; - jpeg_component_info * compptr; - - /* Load up working state */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! emit_restart(&state, entropy->next_restart_num)) - return FALSE; - } - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - if (! encode_one_block(&state, - MCU_data[blkn][0], state.cur.last_dc_val[ci], - entropy->dc_derived_tbls[compptr->dc_tbl_no], - entropy->ac_derived_tbls[compptr->ac_tbl_no])) - return FALSE; - /* Update last_dc_val */ - state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; - } - - /* Completed MCU, so update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * Finish up at the end of a Huffman-compressed scan. - */ - -METHODDEF(void) -finish_pass_huff (j_compress_ptr cinfo) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; - working_state state; - - /* Load up working state ... flush_bits needs it */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Flush out the last data */ - if (! flush_bits(&state)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - - /* Update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); -} - - -/* - * Huffman coding optimization. - * - * We first scan the supplied data and count the number of uses of each symbol - * that is to be Huffman-coded. (This process MUST agree with the code above.) - * Then we build a Huffman coding tree for the observed counts. - * Symbols which are not needed at all for the particular image are not - * assigned any code, which saves space in the DHT marker as well as in - * the compressed data. - */ - -#ifdef ENTROPY_OPT_SUPPORTED - - -/* Process a single block's worth of coefficients */ - -LOCAL(void) -htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, - long dc_counts[], long ac_counts[]) -{ - register int temp; - register int nbits; - register int k, r; - - /* Encode the DC coefficient difference per section F.1.2.1 */ - - temp = block[0] - last_dc_val; - if (temp < 0) - temp = -temp; - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count the Huffman symbol for the number of bits */ - dc_counts[nbits]++; - - /* Encode the AC coefficients per section F.1.2.2 */ - - r = 0; /* r = run length of zeros */ - - for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { - r++; - } else { - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - ac_counts[0xF0]++; - r -= 16; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - if (temp < 0) - temp = -temp; - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count Huffman symbol for run length / number of bits */ - ac_counts[(r << 4) + nbits]++; - - r = 0; - } - } - - /* If the last coef(s) were zero, emit an end-of-block code */ - if (r > 0) - ac_counts[0]++; -} - - -/* - * Trial-encode one MCU's worth of Huffman-compressed coefficients. - * No data is actually output, so no suspension return is possible. - */ - -METHODDEF(boolean) -encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; - int blkn, ci; - jpeg_component_info * compptr; - - /* Take care of restart intervals if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Update restart state */ - entropy->restarts_to_go = cinfo->restart_interval; - } - entropy->restarts_to_go--; - } - - for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], - entropy->dc_count_ptrs[compptr->dc_tbl_no], - entropy->ac_count_ptrs[compptr->ac_tbl_no]); - entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; - } - - return TRUE; -} - - -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - -METHODDEF(void) -finish_pass_gather (j_compress_ptr cinfo) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; - int ci, dctbl, actbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did_dc[NUM_HUFF_TBLS]; - boolean did_ac[NUM_HUFF_TBLS]; - - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ - MEMZERO(did_dc, SIZEOF(did_dc)); - MEMZERO(did_ac, SIZEOF(did_ac)); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (! did_dc[dctbl]) { - htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); - did_dc[dctbl] = TRUE; - } - if (! did_ac[actbl]) { - htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); - did_ac[actbl] = TRUE; - } - } -} - - -#endif /* ENTROPY_OPT_SUPPORTED */ - - -METHODDEF(boolean) -need_optimization_pass (j_compress_ptr cinfo) -{ - return TRUE; -} - - -/* - * Module initialization routine for Huffman entropy encoding. - */ - -GLOBAL(void) -jinit_shuff_encoder (j_compress_ptr cinfo) -{ - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - shuff_entropy_ptr entropy; - int i; - - entropy = (shuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(shuff_entropy_encoder)); - lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy; - lossyc->pub.entropy_start_pass = start_pass_huff; - lossyc->pub.need_optimization_pass = need_optimization_pass; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; -#ifdef ENTROPY_OPT_SUPPORTED - entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; -#endif - } -} diff --git a/uppsrc/plugin/jpg/lib/jctrans.c b/uppsrc/plugin/jpg/lib/jctrans.c index c2387a5cc..38f06e097 100644 --- a/uppsrc/plugin/jpg/lib/jctrans.c +++ b/uppsrc/plugin/jpg/lib/jctrans.c @@ -2,6 +2,7 @@ * jctrans.c * * Copyright (C) 1995-1998, Thomas G. Lane. + * Modified 2000-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -13,14 +14,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy codec */ /* Forward declarations */ LOCAL(void) transencode_master_selection JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); -LOCAL(void) transencode_codec - JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); LOCAL(void) transencode_coef_controller JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); @@ -79,11 +77,18 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, dstinfo->image_height = srcinfo->image_height; dstinfo->input_components = srcinfo->num_components; dstinfo->in_color_space = srcinfo->jpeg_color_space; + dstinfo->jpeg_width = srcinfo->output_width; + dstinfo->jpeg_height = srcinfo->output_height; + dstinfo->min_DCT_h_scaled_size = srcinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_v_scaled_size = srcinfo->min_DCT_v_scaled_size; /* Initialize all parameters to default values */ jpeg_set_defaults(dstinfo); /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. * Fix it to get the right header markers for the image colorspace. + * Note: Entropy table assignment in jpeg_set_colorspace depends + * on color_transform. */ + dstinfo->color_transform = srcinfo->color_transform; jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); dstinfo->data_precision = srcinfo->data_precision; dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; @@ -128,7 +133,7 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); } } - /* Note: we do not copy the source's Huffman table assignments; + /* Note: we do not copy the source's entropy table assignments; * instead we rely on jpeg_set_colorspace to have made a suitable choice. */ } @@ -138,10 +143,10 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, * if the application chooses to copy JFIF 1.02 extension markers from * the source file, we need to copy the version to make sure we don't * emit a file that has 1.02 extensions but a claimed version of 1.01. - * We will *not*, however, copy version info from mislabeled "2.01" files. */ if (srcinfo->saw_JFIF_marker) { - if (srcinfo->JFIF_major_version == 1) { + if (srcinfo->JFIF_major_version == 1 || + srcinfo->JFIF_major_version == 2) { dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; } @@ -161,16 +166,18 @@ LOCAL(void) transencode_master_selection (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { - cinfo->data_unit = DCTSIZE; - /* Although we don't actually use input_components for transcoding, - * jcmaster.c's initial_setup will complain if input_components is 0. - */ - cinfo->input_components = 1; /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, TRUE /* transcode only */); - /* We need a special compression codec. */ - transencode_codec(cinfo, coef_arrays); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) + jinit_arith_encoder(cinfo); + else { + jinit_huff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); jinit_marker_writer(cinfo); @@ -196,6 +203,8 @@ transencode_master_selection (j_compress_ptr cinfo, /* Private buffer controller object */ typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + JDIMENSION iMCU_row_num; /* iMCU row # within image */ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ @@ -205,18 +214,17 @@ typedef struct { jvirt_barray_ptr * whole_image; /* Workspace for constructing dummy blocks at right/bottom edges. */ - JBLOCKROW dummy_buffer[C_MAX_DATA_UNITS_IN_MCU]; -} c_coef_controller; + JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; +} my_coef_controller; -typedef c_coef_controller * c_coef_ptr; +typedef my_coef_controller * my_coef_ptr; LOCAL(void) start_iMCU_row (j_compress_ptr cinfo) /* Reset within-iMCU-row counters for a new row */ { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. @@ -243,8 +251,7 @@ start_iMCU_row (j_compress_ptr cinfo) METHODDEF(void) start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; if (pass_mode != JBUF_CRANK_DEST) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); @@ -267,15 +274,14 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) METHODDEF(boolean) compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, ci, xindex, yindex, yoffset, blockcnt; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU]; + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; @@ -325,7 +331,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) } } /* Try to write the MCU. */ - if (! (*lossyc->entropy_encode_mcu) (cinfo, MCU_buffer)) { + if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; @@ -346,7 +352,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) * Initialize coefficient buffer controller. * * Each passed coefficient array must be the right size for that - * coefficient: width_in_data_units wide and height_in_data_units high, + * coefficient: width_in_blocks wide and height_in_blocks high, * with unitheight at least v_samp_factor. */ @@ -354,15 +360,16 @@ LOCAL(void) transencode_coef_controller (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { - j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; - c_coef_ptr coef; + my_coef_ptr coef; JBLOCKROW buffer; int i; - coef = (c_coef_ptr) + coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(c_coef_controller)); - lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; + SIZEOF(my_coef_controller)); + cinfo->coef = &coef->pub; + coef->pub.start_pass = start_pass_coef; + coef->pub.compress_data = compress_output; /* Save pointer to virtual arrays */ coef->whole_image = coef_arrays; @@ -370,51 +377,9 @@ transencode_coef_controller (j_compress_ptr cinfo, /* Allocate and pre-zero space for dummy DCT blocks. */ buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); - jzero_far((void FAR *) buffer, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + FMEMZERO((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->dummy_buffer[i] = buffer + i; } } - - -/* - * Initialize the transencoer codec. - * This is called only once, during master selection. - */ - -LOCAL(void) -transencode_codec (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) -{ - j_lossy_c_ptr lossyc; - - /* Create subobject in permanent pool */ - lossyc = (j_lossy_c_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(jpeg_lossy_c_codec)); - cinfo->codec = (struct jpeg_c_codec *) lossyc; - - /* Initialize sub-modules */ - - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->process == JPROC_PROGRESSIVE) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_shuff_encoder(cinfo); - } - - /* We need a special coefficient buffer controller. */ - transencode_coef_controller(cinfo, coef_arrays); - - /* Initialize method pointers */ - lossyc->pub.start_pass = start_pass_coef; - lossyc->pub.compress_data = compress_output; -} diff --git a/uppsrc/plugin/jpg/lib/jdapimin.c b/uppsrc/plugin/jpg/lib/jdapimin.c index 70bca3e8f..c1b88f75e 100644 --- a/uppsrc/plugin/jpg/lib/jdapimin.c +++ b/uppsrc/plugin/jpg/lib/jdapimin.c @@ -2,6 +2,7 @@ * jdapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2009-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -36,7 +37,7 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) if (version != JPEG_LIB_VERSION) ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_decompress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); /* For debugging purposes, we zero the whole master structure. @@ -113,19 +114,33 @@ jpeg_abort_decompress (j_decompress_ptr cinfo) LOCAL(void) default_decompress_parms (j_decompress_ptr cinfo) { + int cid0, cid1, cid2; + /* Guess the input colorspace, and set output colorspace accordingly. */ - /* (Wish JPEG committee had provided a real way to specify this...) */ /* Note application may override our guesses. */ switch (cinfo->num_components) { case 1: cinfo->jpeg_color_space = JCS_GRAYSCALE; cinfo->out_color_space = JCS_GRAYSCALE; break; - + case 3: - if (cinfo->saw_JFIF_marker) { - cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ - } else if (cinfo->saw_Adobe_marker) { + cid0 = cinfo->comp_info[0].component_id; + cid1 = cinfo->comp_info[1].component_id; + cid2 = cinfo->comp_info[2].component_id; + + /* First try to guess from the component IDs */ + if (cid0 == 0x01 && cid1 == 0x02 && cid2 == 0x03) + cinfo->jpeg_color_space = JCS_YCbCr; + else if (cid0 == 0x01 && cid1 == 0x22 && cid2 == 0x23) + cinfo->jpeg_color_space = JCS_BG_YCC; + else if (cid0 == 0x52 && cid1 == 0x47 && cid2 == 0x42) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else if (cid0 == 0x72 && cid1 == 0x67 && cid2 == 0x62) + cinfo->jpeg_color_space = JCS_BG_RGB; /* ASCII 'r', 'g', 'b' */ + else if (cinfo->saw_JFIF_marker) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + else if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: cinfo->jpeg_color_space = JCS_RGB; @@ -135,34 +150,17 @@ default_decompress_parms (j_decompress_ptr cinfo) break; default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ break; } } else { - /* Saw no special markers, try to guess from the component IDs */ - int cid0 = cinfo->comp_info[0].component_id; - int cid1 = cinfo->comp_info[1].component_id; - int cid2 = cinfo->comp_info[2].component_id; - - if (cid0 == 1 && cid1 == 2 && cid2 == 3) - cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ - else if (cid0 == 82 && cid1 == 71 && cid2 == 66) - cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ - else { - if (cinfo->process == JPROC_LOSSLESS) { - TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSLESS_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */ - } - else { /* Lossy processes */ - TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSY_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - } - } + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ } /* Always guess RGB is proper output colorspace. */ cinfo->out_color_space = JCS_RGB; break; - + case 4: if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { @@ -174,7 +172,7 @@ default_decompress_parms (j_decompress_ptr cinfo) break; default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ break; } } else { @@ -183,7 +181,7 @@ default_decompress_parms (j_decompress_ptr cinfo) } cinfo->out_color_space = JCS_CMYK; break; - + default: cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->out_color_space = JCS_UNKNOWN; @@ -191,8 +189,8 @@ default_decompress_parms (j_decompress_ptr cinfo) } /* Set defaults for other decompression parameters. */ - cinfo->scale_num = 1; /* 1:1 scaling */ - cinfo->scale_denom = 1; + cinfo->scale_num = cinfo->block_size; /* 1:1 scaling */ + cinfo->scale_denom = cinfo->block_size; cinfo->output_gamma = 1.0; cinfo->buffered_image = FALSE; cinfo->raw_data_out = FALSE; diff --git a/uppsrc/plugin/jpg/lib/jdapistd.c b/uppsrc/plugin/jpg/lib/jdapistd.c index f2c743266..6437dc562 100644 --- a/uppsrc/plugin/jpg/lib/jdapistd.c +++ b/uppsrc/plugin/jpg/lib/jdapistd.c @@ -1,7 +1,8 @@ /* * jdapistd.c * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -202,12 +203,12 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, } /* Verify that at least one iMCU row can be returned. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_codec_data_unit; + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; if (max_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Decompress directly into user's buffer. */ - if (! (*cinfo->codec->decompress_data) (cinfo, data)) + if (! (*cinfo->coef->decompress_data) (cinfo, data)) return 0; /* suspension forced, can do nothing more */ /* OK, we processed one iMCU row. */ diff --git a/uppsrc/plugin/jpg/lib/jdarith.c b/uppsrc/plugin/jpg/lib/jdarith.c new file mode 100644 index 000000000..14ca7fe13 --- /dev/null +++ b/uppsrc/plugin/jpg/lib/jdarith.c @@ -0,0 +1,796 @@ +/* + * jdarith.c + * + * Developed 1997-2015 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains portable arithmetic entropy decoding routines for JPEG + * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). + * + * Both sequential and progressive modes are supported in this single module. + * + * Suspension is not currently supported in this module. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Expanded entropy decoder object for arithmetic decoding. */ + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + INT32 c; /* C register, base of coding interval + input bit buffer */ + INT32 a; /* A register, normalized size of coding interval */ + int ct; /* bit shift counter, # of bits left in bit buffer part of C */ + /* init: ct = -16 */ + /* run: ct = 0..7 */ + /* error: ct = -1 */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to statistics areas (these workspaces have image lifespan) */ + unsigned char * dc_stats[NUM_ARITH_TBLS]; + unsigned char * ac_stats[NUM_ARITH_TBLS]; + + /* Statistics bin for coding with fixed probability 0.5 */ + unsigned char fixed_bin[4]; +} arith_entropy_decoder; + +typedef arith_entropy_decoder * arith_entropy_ptr; + +/* The following two definitions specify the allocation chunk size + * for the statistics area. + * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least + * 49 statistics bins for DC, and 245 statistics bins for AC coding. + * + * We use a compact representation with 1 byte per statistics bin, + * thus the numbers directly represent byte sizes. + * This 1 byte per statistics bin contains the meaning of the MPS + * (more probable symbol) in the highest bit (mask 0x80), and the + * index into the probability estimation state machine table + * in the lower bits (mask 0x7F). + */ + +#define DC_STAT_BINS 64 +#define AC_STAT_BINS 256 + + +LOCAL(int) +get_byte (j_decompress_ptr cinfo) +/* Read next input byte; we do not support suspension in this module. */ +{ + struct jpeg_source_mgr * src = cinfo->src; + + if (src->bytes_in_buffer == 0) + if (! (*src->fill_input_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + src->bytes_in_buffer--; + return GETJOCTET(*src->next_input_byte++); +} + + +/* + * The core arithmetic decoding routine (common in JPEG and JBIG). + * This needs to go as fast as possible. + * Machine-dependent optimization facilities + * are not utilized in this portable implementation. + * However, this code should be fairly efficient and + * may be a good base for further optimizations anyway. + * + * Return value is 0 or 1 (binary decision). + * + * Note: I've changed the handling of the code base & bit + * buffer register C compared to other implementations + * based on the standards layout & procedures. + * While it also contains both the actual base of the + * coding interval (16 bits) and the next-bits buffer, + * the cut-point between these two parts is floating + * (instead of fixed) with the bit shift counter CT. + * Thus, we also need only one (variable instead of + * fixed size) shift for the LPS/MPS decision, and + * we can do away with any renormalization update + * of C (except for new data insertion, of course). + * + * I've also introduced a new scheme for accessing + * the probability estimation state machine table, + * derived from Markus Kuhn's JBIG implementation. + */ + +LOCAL(int) +arith_decode (j_decompress_ptr cinfo, unsigned char *st) +{ + register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + register unsigned char nl, nm; + register INT32 qe, temp; + register int sv, data; + + /* Renormalization & data input per section D.2.6 */ + while (e->a < 0x8000L) { + if (--e->ct < 0) { + /* Need to fetch next data byte */ + if (cinfo->unread_marker) + data = 0; /* stuff zero data */ + else { + data = get_byte(cinfo); /* read next input byte */ + if (data == 0xFF) { /* zero stuff or marker code */ + do data = get_byte(cinfo); + while (data == 0xFF); /* swallow extra 0xFF bytes */ + if (data == 0) + data = 0xFF; /* discard stuffed zero byte */ + else { + /* Note: Different from the Huffman decoder, hitting + * a marker while processing the compressed data + * segment is legal in arithmetic coding. + * The convention is to supply zero data + * then until decoding is complete. + */ + cinfo->unread_marker = data; + data = 0; + } + } + } + e->c = (e->c << 8) | data; /* insert data into C register */ + if ((e->ct += 8) < 0) /* update bit shift counter */ + /* Need more initial bytes */ + if (++e->ct == 0) + /* Got 2 initial bytes -> re-init A and exit loop */ + e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */ + } + e->a <<= 1; + } + + /* Fetch values from our compact representation of Table D.3(D.2): + * Qe values and probability estimation state machine + */ + sv = *st; + qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ + nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ + nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ + + /* Decode & estimation procedures per sections D.2.4 & D.2.5 */ + temp = e->a - qe; + e->a = temp; + temp <<= e->ct; + if (e->c >= temp) { + e->c -= temp; + /* Conditional LPS (less probable symbol) exchange */ + if (e->a < qe) { + e->a = qe; + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } else { + e->a = qe; + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + sv ^= 0x80; /* Exchange LPS/MPS */ + } + } else if (e->a < 0x8000L) { + /* Conditional MPS (more probable symbol) exchange */ + if (e->a < qe) { + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + sv ^= 0x80; /* Exchange LPS/MPS */ + } else { + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } + } + + return sv >> 7; +} + + +/* + * Check for a restart marker & resynchronize decoder. + */ + +LOCAL(void) +process_restart (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci; + jpeg_component_info * compptr; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Re-initialize statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { + MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); + /* Reset DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + if ((! cinfo->progressive_mode && cinfo->lim_Se) || + (cinfo->progressive_mode && cinfo->Ss)) { + MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); + } + } + + /* Reset arithmetic decoding variables */ + entropy->c = 0; + entropy->a = 0; + entropy->ct = -16; /* force reading 2 initial bytes to fill C */ + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Arithmetic MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * arithmetic-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl, sign; + int v, m; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; + + /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.19: Decode_DC_DIFF */ + if (arith_decode(cinfo, st) == 0) + entropy->dc_context[ci] = 0; + else { + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, st + 1); + st += 2; st += sign; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ + else + entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + entropy->last_dc_val[ci] += v; + } + + /* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (entropy->last_dc_val[ci] << cinfo->Al); + } + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int tbl, sign, k; + int v, m; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ + + /* Figure F.20: Decode_AC_coefficients */ + k = cinfo->Ss - 1; + do { + st = entropy->ac_stats[tbl] + 3 * k; + if (arith_decode(cinfo, st)) break; /* EOB flag */ + for (;;) { + k++; + if (arith_decode(cinfo, st + 1)) break; + st += 3; + if (k >= cinfo->Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, entropy->fixed_bin); + st += 2; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + if (arith_decode(cinfo, st)) { + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + } + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[natural_order[k]] = (JCOEF) (v << cinfo->Al); + } while (k < cinfo->Se); + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, + * although the spec is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + unsigned char *st; + int p1, blkn; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + st = entropy->fixed_bin; /* use fixed probability estimation */ + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* Encoded data is simply the next bit of the two's-complement DC value */ + if (arith_decode(cinfo, st)) + MCU_data[blkn][0][0] |= p1; + } + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + JCOEFPTR thiscoef; + unsigned char *st; + int tbl, k, kex; + int p1, m1; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + + /* Establish EOBx (previous stage end-of-block) index */ + kex = cinfo->Se; + do { + if ((*block)[natural_order[kex]]) break; + } while (--kex); + + k = cinfo->Ss - 1; + do { + st = entropy->ac_stats[tbl] + 3 * k; + if (k >= kex) + if (arith_decode(cinfo, st)) break; /* EOB flag */ + for (;;) { + thiscoef = *block + natural_order[++k]; + if (*thiscoef) { /* previously nonzero coef */ + if (arith_decode(cinfo, st + 2)) { + if (*thiscoef < 0) + *thiscoef += m1; + else + *thiscoef += p1; + } + break; + } + if (arith_decode(cinfo, st + 1)) { /* newly nonzero coef */ + if (arith_decode(cinfo, entropy->fixed_bin)) + *thiscoef = m1; + else + *thiscoef = p1; + break; + } + st += 3; + if (k >= cinfo->Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + } while (k < cinfo->Se); + + return TRUE; +} + + +/* + * Decode one MCU's worth of arithmetic-compressed coefficients. + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + jpeg_component_info * compptr; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl, sign, k; + int v, m; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ + + tbl = compptr->dc_tbl_no; + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.19: Decode_DC_DIFF */ + if (arith_decode(cinfo, st) == 0) + entropy->dc_context[ci] = 0; + else { + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, st + 1); + st += 2; st += sign; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ + else + entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + entropy->last_dc_val[ci] += v; + } + + (*block)[0] = (JCOEF) entropy->last_dc_val[ci]; + + /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ + + if (cinfo->lim_Se == 0) continue; + tbl = compptr->ac_tbl_no; + k = 0; + + /* Figure F.20: Decode_AC_coefficients */ + do { + st = entropy->ac_stats[tbl] + 3 * k; + if (arith_decode(cinfo, st)) break; /* EOB flag */ + for (;;) { + k++; + if (arith_decode(cinfo, st + 1)) break; + st += 3; + if (k >= cinfo->lim_Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, entropy->fixed_bin); + st += 2; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + if (arith_decode(cinfo, st)) { + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + } + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + (*block)[natural_order[k]] = (JCOEF) v; + } while (k < cinfo->lim_Se); + } + + return TRUE; +} + + +/* + * Initialize for an arithmetic-compressed scan. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (cinfo->progressive_mode) { + /* Validate progressive scan parameters */ + if (cinfo->Ss == 0) { + if (cinfo->Se != 0) + goto bad; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) + goto bad; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + goto bad; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Ah-1 != cinfo->Al) + goto bad; + } + if (cinfo->Al > 13) { /* need not check for < 0 */ + bad: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + } + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; + int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + } else { + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning. + */ + if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || + (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + /* Select MCU decoding routine */ + entropy->pub.decode_mcu = decode_mcu; + } + + /* Allocate & initialize requested statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { + tbl = compptr->dc_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->dc_stats[tbl] == NULL) + entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); + MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + if ((! cinfo->progressive_mode && cinfo->lim_Se) || + (cinfo->progressive_mode && cinfo->Ss)) { + tbl = compptr->ac_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->ac_stats[tbl] == NULL) + entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); + MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); + } + } + + /* Initialize arithmetic decoding variables */ + entropy->c = 0; + entropy->a = 0; + entropy->ct = -16; /* force reading 2 initial bytes to fill C */ + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Finish up at the end of an arithmetic-compressed scan. + */ + +METHODDEF(void) +finish_pass (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Module initialization routine for arithmetic entropy decoding. + */ + +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy; + int i; + + entropy = (arith_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(arith_entropy_decoder)); + cinfo->entropy = &entropy->pub; + entropy->pub.start_pass = start_pass; + entropy->pub.finish_pass = finish_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + entropy->dc_stats[i] = NULL; + entropy->ac_stats[i] = NULL; + } + + /* Initialize index for fixed probability estimation */ + entropy->fixed_bin[0] = 113; + + if (cinfo->progressive_mode) { + /* Create progression status table */ + int *coef_bit_ptr, ci; + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; + } +} diff --git a/uppsrc/plugin/jpg/lib/jdatadst.c b/uppsrc/plugin/jpg/lib/jdatadst.c index 2ece4e95d..677e46346 100644 --- a/uppsrc/plugin/jpg/lib/jdatadst.c +++ b/uppsrc/plugin/jpg/lib/jdatadst.c @@ -2,13 +2,14 @@ * jdatadst.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2012 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression data destination routines for the case of - * emitting JPEG data to a file (or any stdio stream). While these routines - * are sufficient for most applications, some will want to use a different - * destination manager. + * emitting JPEG data to memory or to a file (or any stdio stream). + * While these routines are sufficient for most applications, + * some will want to use a different destination manager. * IMPORTANT: we assume that fwrite() will correctly transcribe an array of * JOCTETs into 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. @@ -19,6 +20,11 @@ #include "jpeglib.h" #include "jerror.h" +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + /* Expanded data destination object for stdio output */ @@ -34,6 +40,21 @@ typedef my_destination_mgr * my_dest_ptr; #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ +/* Expanded data destination object for memory output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + unsigned char ** outbuffer; /* target buffer */ + unsigned long * outsize; + unsigned char * newbuffer; /* newly allocated buffer */ + JOCTET * buffer; /* start of buffer */ + size_t bufsize; +} my_mem_destination_mgr; + +typedef my_mem_destination_mgr * my_mem_dest_ptr; + + /* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. @@ -53,6 +74,12 @@ init_destination (j_compress_ptr cinfo) dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } +METHODDEF(void) +init_mem_destination (j_compress_ptr cinfo) +{ + /* no work necessary here */ +} + /* * Empty the output buffer --- called whenever buffer fills up. @@ -92,6 +119,36 @@ empty_output_buffer (j_compress_ptr cinfo) return TRUE; } +METHODDEF(boolean) +empty_mem_output_buffer (j_compress_ptr cinfo) +{ + size_t nextsize; + JOCTET * nextbuffer; + my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; + + /* Try to allocate new buffer with double size */ + nextsize = dest->bufsize * 2; + nextbuffer = (JOCTET *) malloc(nextsize); + + if (nextbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + + MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); + + if (dest->newbuffer != NULL) + free(dest->newbuffer); + + dest->newbuffer = nextbuffer; + + dest->pub.next_output_byte = nextbuffer + dest->bufsize; + dest->pub.free_in_buffer = dest->bufsize; + + dest->buffer = nextbuffer; + dest->bufsize = nextsize; + + return TRUE; +} + /* * Terminate destination --- called by jpeg_finish_compress @@ -119,6 +176,15 @@ term_destination (j_compress_ptr cinfo) ERREXIT(cinfo, JERR_FILE_WRITE); } +METHODDEF(void) +term_mem_destination (j_compress_ptr cinfo) +{ + my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; + + *dest->outbuffer = dest->buffer; + *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; +} + /* * Prepare for output to a stdio stream. @@ -149,3 +215,56 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) dest->pub.term_destination = term_destination; dest->outfile = outfile; } + + +/* + * Prepare for output to a memory buffer. + * The caller may supply an own initial buffer with appropriate size. + * Otherwise, or when the actual data output exceeds the given size, + * the library adapts the buffer size as necessary. + * The standard library functions malloc/free are used for allocating + * larger memory, so the buffer is available to the application after + * finishing compression, and then the application is responsible for + * freeing the requested memory. + * Note: An initial buffer supplied by the caller is expected to be + * managed by the application. The library does not free such buffer + * when allocating a larger buffer. + */ + +GLOBAL(void) +jpeg_mem_dest (j_compress_ptr cinfo, + unsigned char ** outbuffer, unsigned long * outsize) +{ + my_mem_dest_ptr dest; + + if (outbuffer == NULL || outsize == NULL) /* sanity check */ + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same buffer without re-executing jpeg_mem_dest. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_mem_destination_mgr)); + } + + dest = (my_mem_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_mem_destination; + dest->pub.empty_output_buffer = empty_mem_output_buffer; + dest->pub.term_destination = term_mem_destination; + dest->outbuffer = outbuffer; + dest->outsize = outsize; + dest->newbuffer = NULL; + + if (*outbuffer == NULL || *outsize == 0) { + /* Allocate initial buffer */ + dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE); + if (dest->newbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + *outsize = OUTPUT_BUF_SIZE; + } + + dest->pub.next_output_byte = dest->buffer = *outbuffer; + dest->pub.free_in_buffer = dest->bufsize = *outsize; +} diff --git a/uppsrc/plugin/jpg/lib/jdatasrc.c b/uppsrc/plugin/jpg/lib/jdatasrc.c index 29b698328..c44d8d0ba 100644 --- a/uppsrc/plugin/jpg/lib/jdatasrc.c +++ b/uppsrc/plugin/jpg/lib/jdatasrc.c @@ -2,13 +2,14 @@ * jdatasrc.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression data source routines for the case of - * reading JPEG data from a file (or any stdio stream). While these routines - * are sufficient for most applications, some will want to use a different - * source manager. + * reading JPEG data from memory or from a file (or any stdio stream). + * While these routines are sufficient for most applications, + * some will want to use a different source manager. * IMPORTANT: we assume that fread() will correctly transcribe an array of * JOCTETs from 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. @@ -52,6 +53,12 @@ init_source (j_decompress_ptr cinfo) src->start_of_file = TRUE; } +METHODDEF(void) +init_mem_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + /* * Fill the input buffer --- called whenever buffer is emptied. @@ -111,6 +118,27 @@ fill_input_buffer (j_decompress_ptr cinfo) return TRUE; } +METHODDEF(boolean) +fill_mem_input_buffer (j_decompress_ptr cinfo) +{ + static const JOCTET mybuffer[4] = { + (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0 + }; + + /* The whole JPEG data is expected to reside in the supplied memory + * buffer, so any request for more data beyond the given buffer size + * is treated as an error. + */ + WARNMS(cinfo, JWRN_JPEG_EOF); + + /* Insert a fake EOI marker */ + + cinfo->src->next_input_byte = mybuffer; + cinfo->src->bytes_in_buffer = 2; + + return TRUE; +} + /* * Skip data --- used to skip over a potentially large amount of @@ -127,22 +155,22 @@ fill_input_buffer (j_decompress_ptr cinfo) METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - my_src_ptr src = (my_src_ptr) cinfo->src; + struct jpeg_source_mgr * src = cinfo->src; /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. */ if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer(cinfo); + while (num_bytes > (long) src->bytes_in_buffer) { + num_bytes -= (long) src->bytes_in_buffer; + (void) (*src->fill_input_buffer) (cinfo); /* note we assume that fill_input_buffer will never return FALSE, * so suspension need not be handled. */ } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; + src->next_input_byte += (size_t) num_bytes; + src->bytes_in_buffer -= (size_t) num_bytes; } } @@ -210,3 +238,38 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */ } + + +/* + * Prepare for input from a supplied memory buffer. + * The buffer must contain the whole JPEG data. + */ + +GLOBAL(void) +jpeg_mem_src (j_decompress_ptr cinfo, + const unsigned char * inbuffer, unsigned long insize) +{ + struct jpeg_source_mgr * src; + + if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + + /* The source object is made permanent so that a series of JPEG images + * can be read from the same buffer by calling jpeg_mem_src only before + * the first one. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(struct jpeg_source_mgr)); + } + + src = cinfo->src; + src->init_source = init_mem_source; + src->fill_input_buffer = fill_mem_input_buffer; + src->skip_input_data = skip_input_data; + src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->term_source = term_source; + src->bytes_in_buffer = (size_t) insize; + src->next_input_byte = (const JOCTET *) inbuffer; +} diff --git a/uppsrc/plugin/jpg/lib/jdcoefct.c b/uppsrc/plugin/jpg/lib/jdcoefct.c index 9a7025a5b..75ee51f0f 100644 --- a/uppsrc/plugin/jpg/lib/jdcoefct.c +++ b/uppsrc/plugin/jpg/lib/jdcoefct.c @@ -1,12 +1,13 @@ /* * jdcoefct.c * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2002-2011 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the coefficient buffer controller for decompression. - * This controller is the top level of the lossy JPEG decompressor proper. + * This controller is the top level of the JPEG decompressor proper. * The coefficient buffer lies between entropy decoding and inverse-DCT steps. * * In buffered-image mode, this controller is the interface between @@ -17,7 +18,6 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jlossy.h" /* Block smoothing is only applicable for progressive JPEG, so: */ #ifndef D_PROGRESSIVE_SUPPORTED @@ -27,6 +27,8 @@ /* Private buffer controller object */ typedef struct { + struct jpeg_d_coef_controller pub; /* public fields */ + /* These variables keep track of the current location of the input side. */ /* cinfo->input_iMCU_row is also used for this. */ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ @@ -36,7 +38,7 @@ typedef struct { /* The output side's location is represented by cinfo->output_iMCU_row. */ /* In single-pass modes, it's sufficient to buffer just one MCU. - * We allocate a workspace of D_MAX_DATA_UNITS_IN_MCU coefficient blocks, + * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, * and let the entropy decoder write into that workspace each time. * (On 80x86, the workspace is FAR even though it's not really very big; * this is to keep the module interfaces unchanged when a large coefficient @@ -44,7 +46,7 @@ typedef struct { * In multi-pass modes, this array points to the current MCU's blocks * within the virtual arrays; it is used only by the input side. */ - JBLOCKROW MCU_buffer[D_MAX_DATA_UNITS_IN_MCU]; + JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; #ifdef D_MULTISCAN_FILES_SUPPORTED /* In multi-pass modes, we need a virtual block array for each component. */ @@ -56,9 +58,9 @@ typedef struct { int * coef_bits_latch; #define SAVED_COEFS 6 /* we save coef_bits[0..5] */ #endif -} d_coef_controller; +} my_coef_controller; -typedef d_coef_controller * d_coef_ptr; +typedef my_coef_controller * my_coef_ptr; /* Forward declarations */ METHODDEF(int) decompress_onepass @@ -78,8 +80,7 @@ LOCAL(void) start_iMCU_row (j_decompress_ptr cinfo) /* Reset within-iMCU-row counters for a new row (input side) */ { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. @@ -119,15 +120,14 @@ METHODDEF(void) start_output_pass (j_decompress_ptr cinfo) { #ifdef BLOCK_SMOOTHING_SUPPORTED - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; -// d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* If multipass, check to see whether to use block smoothing on this pass */ - if (lossyd->coef_arrays != NULL) { + if (coef->pub.coef_arrays != NULL) { if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) - lossyd->pub.decompress_data = decompress_smooth_data; + coef->pub.decompress_data = decompress_smooth_data; else - lossyd->pub.decompress_data = decompress_data; + coef->pub.decompress_data = decompress_data; } #endif cinfo->output_iMCU_row = 0; @@ -147,8 +147,7 @@ start_output_pass (j_decompress_ptr cinfo) METHODDEF(int) decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; @@ -164,9 +163,10 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ - jzero_far((void FAR *) coef->MCU_buffer[0], - (size_t) (cinfo->data_units_in_MCU * SIZEOF(JBLOCK))); - if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) { + if (cinfo->lim_Se) /* can bypass in DC only case */ + FMEMZERO((void FAR *) coef->MCU_buffer[0], + (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; @@ -182,14 +182,14 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) compptr = cinfo->cur_comp_info[ci]; /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) { - blkn += compptr->MCU_data_units; + blkn += compptr->MCU_blocks; continue; } - inverse_DCT = lossyd->inverse_DCT[compptr->component_index]; + inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; output_ptr = output_buf[compptr->component_index] + - yoffset * compptr->codec_data_unit; + yoffset * compptr->DCT_v_scaled_size; start_col = MCU_col_num * compptr->MCU_sample_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (cinfo->input_iMCU_row < last_iMCU_row || @@ -199,11 +199,11 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) coef->MCU_buffer[blkn+xindex], output_ptr, output_col); - output_col += compptr->codec_data_unit; + output_col += compptr->DCT_h_scaled_size; } } blkn += compptr->MCU_width; - output_ptr += compptr->codec_data_unit; + output_ptr += compptr->DCT_v_scaled_size; } } } @@ -245,8 +245,7 @@ dummy_consume_data (j_decompress_ptr cinfo) METHODDEF(int) consume_data (j_decompress_ptr cinfo) { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int blkn, ci, xindex, yindex, yoffset; JDIMENSION start_col; @@ -285,7 +284,7 @@ consume_data (j_decompress_ptr cinfo) } } /* Try to fetch the MCU. */ - if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) { + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; @@ -317,8 +316,7 @@ consume_data (j_decompress_ptr cinfo) METHODDEF(int) decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION block_num; int ci, block_row, block_rows; @@ -353,22 +351,22 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor); + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } - inverse_DCT = lossyd->inverse_DCT[ci]; + inverse_DCT = cinfo->idct->inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { buffer_ptr = buffer[block_row]; output_col = 0; - for (block_num = 0; block_num < compptr->width_in_data_units; block_num++) { + for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, output_ptr, output_col); buffer_ptr++; - output_col += compptr->codec_data_unit; + output_col += compptr->DCT_h_scaled_size; } - output_ptr += compptr->codec_data_unit; + output_ptr += compptr->DCT_v_scaled_size; } } @@ -408,8 +406,7 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) LOCAL(boolean) smoothing_ok (j_decompress_ptr cinfo) { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; boolean smoothing_useful = FALSE; int ci, coefi; jpeg_component_info *compptr; @@ -417,7 +414,7 @@ smoothing_ok (j_decompress_ptr cinfo) int * coef_bits; int * coef_bits_latch; - if (! cinfo->process == JPROC_PROGRESSIVE || cinfo->coef_bits == NULL) + if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) return FALSE; /* Allocate latch area if not already done */ @@ -465,8 +462,7 @@ smoothing_ok (j_decompress_ptr cinfo) METHODDEF(int) decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION block_num, last_block_column; int ci, block_row, block_rows, access_rows; @@ -514,7 +510,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) last_row = FALSE; } else { /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor); + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; access_rows = block_rows; /* this iMCU row only */ last_row = TRUE; @@ -543,7 +539,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) Q20 = quanttbl->quantval[Q20_POS]; Q11 = quanttbl->quantval[Q11_POS]; Q02 = quanttbl->quantval[Q02_POS]; - inverse_DCT = lossyd->inverse_DCT[ci]; + inverse_DCT = cinfo->idct->inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { @@ -563,7 +559,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; DC7 = DC8 = DC9 = (int) next_block_row[0][0]; output_col = 0; - last_block_column = compptr->width_in_data_units - 1; + last_block_column = compptr->width_in_blocks - 1; for (block_num = 0; block_num <= last_block_column; block_num++) { /* Fetch current DCT block into workspace so we can modify it. */ jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); @@ -660,9 +656,9 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) DC4 = DC5; DC5 = DC6; DC7 = DC8; DC8 = DC9; buffer_ptr++, prev_block_row++, next_block_row++; - output_col += compptr->codec_data_unit; + output_col += compptr->DCT_h_scaled_size; } - output_ptr += compptr->codec_data_unit; + output_ptr += compptr->DCT_v_scaled_size; } } @@ -681,15 +677,14 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) GLOBAL(void) jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - d_coef_ptr coef; + my_coef_ptr coef; - coef = (d_coef_ptr) + coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(d_coef_controller)); - lossyd->coef_private = (void *) coef; - lossyd->coef_start_input_pass = start_input_pass; - lossyd->coef_start_output_pass = start_output_pass; + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_d_coef_controller *) coef; + coef->pub.start_input_pass = start_input_pass; + coef->pub.start_output_pass = start_output_pass; #ifdef BLOCK_SMOOTHING_SUPPORTED coef->coef_bits_latch = NULL; #endif @@ -708,20 +703,20 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) access_rows = compptr->v_samp_factor; #ifdef BLOCK_SMOOTHING_SUPPORTED /* If block smoothing could be used, need a bigger window */ - if (cinfo->process == JPROC_PROGRESSIVE) + if (cinfo->progressive_mode) access_rows *= 3; #endif coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) access_rows); } - lossyd->pub.consume_data = consume_data; - lossyd->pub.decompress_data = decompress_data; - lossyd->coef_arrays = coef->whole_image; /* link to virtual arrays */ + coef->pub.consume_data = consume_data; + coef->pub.decompress_data = decompress_data; + coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif @@ -732,12 +727,15 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - D_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < D_MAX_DATA_UNITS_IN_MCU; i++) { + D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } - lossyd->pub.consume_data = dummy_consume_data; - lossyd->pub.decompress_data = decompress_onepass; - lossyd->coef_arrays = NULL; /* flag for no virtual arrays */ + if (cinfo->lim_Se == 0) /* DC only case: want to bypass later */ + FMEMZERO((void FAR *) buffer, + (size_t) (D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK))); + coef->pub.consume_data = dummy_consume_data; + coef->pub.decompress_data = decompress_onepass; + coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ } } diff --git a/uppsrc/plugin/jpg/lib/jdcolor.c b/uppsrc/plugin/jpg/lib/jdcolor.c index fd7b13887..92d3c1a58 100644 --- a/uppsrc/plugin/jpg/lib/jdcolor.c +++ b/uppsrc/plugin/jpg/lib/jdcolor.c @@ -2,6 +2,7 @@ * jdcolor.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2011-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -18,27 +19,57 @@ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ - /* Private state for YCC->RGB conversion */ + /* Private state for YCbCr->RGB and BG_YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* Private state for RGB->Y conversion */ + INT32 * rgb_y_tab; /* => table for RGB to Y conversion */ } my_color_deconverter; typedef my_color_deconverter * my_cconvert_ptr; -/**************** YCbCr -> RGB conversion: most common case **************/ +/*************** YCbCr -> RGB conversion: most common case **************/ +/*************** BG_YCC -> RGB conversion: less common case **************/ +/*************** RGB -> Y conversion: less common case **************/ /* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * R = Y + 1.40200 * Cr - * G = Y - 0.34414 * Cb - 0.71414 * Cr - * B = Y + 1.77200 * Cb + * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011), + * previously known as Recommendation CCIR 601-1, except that Cb and Cr + * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999. + * sYCC (standard luma-chroma-chroma color space with extended gamut) + * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F. + * bg-sRGB and bg-sYCC (big gamut standard color spaces) + * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G. + * Note that the derived conversion coefficients given in some of these + * documents are imprecise. The general conversion equations are + * + * R = Y + K * (1 - Kr) * Cr + * G = Y - K * (Kb * (1 - Kb) * Cb + Kr * (1 - Kr) * Cr) / (1 - Kr - Kb) + * B = Y + K * (1 - Kb) * Cb + * + * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B + * + * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993 + * from the 1953 FCC NTSC primaries and CIE Illuminant C), K = 2 for sYCC, + * the conversion equations to be implemented are therefore + * + * R = Y + 1.402 * Cr + * G = Y - 0.344136286 * Cb - 0.714136286 * Cr + * B = Y + 1.772 * Cb + * + * Y = 0.299 * R + 0.587 * G + 0.114 * B + * * where Cb and Cr represent the incoming values less CENTERJSAMPLE. - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * For bg-sYCC, with K = 4, the equations are + * + * R = Y + 2.804 * Cr + * G = Y - 0.688272572 * Cb - 1.428272572 * Cr + * B = Y + 3.544 * Cb * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide @@ -49,9 +80,9 @@ typedef my_color_deconverter * my_cconvert_ptr; * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. + * for 9-bit to 12-bit samples it is still acceptable. It's not very + * reasonable for 16-bit samples, but if you want lossless storage you + * shouldn't be changing colorspace anyway. * The Cr=>R and Cb=>B values can be rounded to integers in advance; the * values for the G calculation are left scaled up, since we must add them * together before rounding. @@ -61,13 +92,26 @@ typedef my_color_deconverter * my_cconvert_ptr; #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<Y conversion and divide it up into + * three parts, instead of doing three alloc_small requests. This lets us + * use a single table base address, which can be held in a register in the + * inner loops on many machines (more than can hold all three addresses, + * anyway). + */ + +#define R_Y_OFF 0 /* offset to R => Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define TABLE_SIZE (3*(MAXJSAMPLE+1)) + /* - * Initialize tables for YCC->RGB colorspace conversion. + * Initialize tables for YCbCr->RGB and BG_YCC->RGB colorspace conversion. */ LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) +/* Normal case, sYCC */ { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; int i; @@ -90,17 +134,57 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ + /* Cr=>R value is nearest int to 1.402 * x */ cconvert->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ + RIGHT_SHIFT(FIX(1.402) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.772 * x */ cconvert->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ + RIGHT_SHIFT(FIX(1.772) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.714136286 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.714136286)) * x; + /* Cb=>G value is scaled-up -0.344136286 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ - cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + cconvert->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF; + } +} + + +LOCAL(void) +build_bg_ycc_rgb_table (j_decompress_ptr cinfo) +/* Wide gamut case, bg-sYCC */ +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + INT32 x; + SHIFT_TEMPS + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + cconvert->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 2.804 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(2.804) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 3.544 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(3.544) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -1.428272572 * x */ + cconvert->Cr_g_tab[i] = (- FIX(1.428272572)) * x; + /* Cb=>G value is scaled-up -0.688272572 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF; } } @@ -145,19 +229,196 @@ ycc_rgb_convert (j_decompress_ptr cinfo, y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + /* Range-limiting is essential due to noise introduced by DCT losses, + * for extended gamut (sYCC) and wide gamut (bg-sYCC) encodings. + */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; outptr[RGB_GREEN] = range_limit[y + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; - outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; outptr += RGB_PIXELSIZE; } } } -/**************** Cases other than YCbCr -> RGB **************/ +/**************** Cases other than YCC -> RGB ****************/ + + +/* + * Initialize for RGB->grayscale colorspace conversion. + */ + +LOCAL(void) +build_rgb_y_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + INT32 * rgb_y_tab; + INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_y_tab[i+R_Y_OFF] = FIX(0.299) * i; + rgb_y_tab[i+G_Y_OFF] = FIX(0.587) * i; + rgb_y_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF; + } +} + + +/* + * Convert RGB to grayscale. + */ + +METHODDEF(void) +rgb_gray_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register INT32 * ctab = cconvert->rgb_y_tab; + register int r, g, b; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr0[col]); + g = GETJSAMPLE(inptr1[col]); + b = GETJSAMPLE(inptr2[col]); + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * [R-G,G,B-G] to [R,G,B] conversion with modulo calculation + * (inverse color transform). + * This can be seen as an adaption of the general YCbCr->RGB + * conversion equation with Kr = Kb = 0, while replacing the + * normalization by modulo calculation. + */ + +METHODDEF(void) +rgb1_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register int r, g, b; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr0[col]); + g = GETJSAMPLE(inptr1[col]); + b = GETJSAMPLE(inptr2[col]); + /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD + * (modulo) operator is equivalent to the bitmask operator AND. + */ + outptr[RGB_RED] = (JSAMPLE) ((r + g - CENTERJSAMPLE) & MAXJSAMPLE); + outptr[RGB_GREEN] = (JSAMPLE) g; + outptr[RGB_BLUE] = (JSAMPLE) ((b + g - CENTERJSAMPLE) & MAXJSAMPLE); + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * [R-G,G,B-G] to grayscale conversion with modulo calculation + * (inverse color transform). + */ + +METHODDEF(void) +rgb1_gray_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register INT32 * ctab = cconvert->rgb_y_tab; + register int r, g, b; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr0[col]); + g = GETJSAMPLE(inptr1[col]); + b = GETJSAMPLE(inptr2[col]); + /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD + * (modulo) operator is equivalent to the bitmask operator AND. + */ + r = (r + g - CENTERJSAMPLE) & MAXJSAMPLE; + b = (b + g - CENTERJSAMPLE) & MAXJSAMPLE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * No colorspace change, but conversion from separate-planes + * to interleaved representation. + */ + +METHODDEF(void) +rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = inptr0[col]; + outptr[RGB_GREEN] = inptr1[col]; + outptr[RGB_BLUE] = inptr2[col]; + outptr += RGB_PIXELSIZE; + } + } +} /* @@ -170,19 +431,20 @@ null_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; - register JDIMENSION count; - register int num_components = cinfo->num_components; - JDIMENSION num_cols = cinfo->output_width; int ci; + register int nc = cinfo->num_components; + register JSAMPROW outptr; + register JSAMPROW inptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { - for (ci = 0; ci < num_components; ci++) { + for (ci = 0; ci < nc; ci++) { inptr = input_buf[ci][input_row]; outptr = output_buf[0] + ci; - for (count = num_cols; count > 0; count--) { + for (col = 0; col < num_cols; col++) { *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ - outptr += num_components; + outptr += nc; } } input_row++; @@ -193,7 +455,7 @@ null_convert (j_decompress_ptr cinfo, /* * Color conversion for grayscale: just copy the data. - * This also works for YCbCr -> grayscale conversion, in which + * This also works for YCC -> grayscale conversion, in which * we just copy the Y (luminance) component and ignore chrominance. */ @@ -218,7 +480,8 @@ gray_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; + register JSAMPROW outptr; + register JSAMPROW inptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -271,7 +534,9 @@ ycck_cmyk_convert (j_decompress_ptr cinfo, y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ + /* Range-limiting is essential due to noise introduced by DCT losses, + * and for extended gamut encodings (sYCC). + */ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], @@ -309,7 +574,7 @@ jinit_color_deconverter (j_decompress_ptr cinfo) cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_deconverter)); - cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cinfo->cconvert = &cconvert->pub; cconvert->pub.start_pass = start_pass_dcolor; /* Make sure num_components agrees with jpeg_color_space */ @@ -321,6 +586,8 @@ jinit_color_deconverter (j_decompress_ptr cinfo) case JCS_RGB: case JCS_YCbCr: + case JCS_BG_RGB: + case JCS_BG_YCC: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; @@ -337,6 +604,12 @@ jinit_color_deconverter (j_decompress_ptr cinfo) break; } + /* Support color transform only for RGB colorspaces */ + if (cinfo->color_transform && + cinfo->jpeg_color_space != JCS_RGB && + cinfo->jpeg_color_space != JCS_BG_RGB) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + /* Set out_color_components and conversion method based on requested space. * Also clear the component_needed flags for any unused components, * so that earlier pipeline stages can avoid useless computation. @@ -345,38 +618,94 @@ jinit_color_deconverter (j_decompress_ptr cinfo) switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; - if (cinfo->jpeg_color_space == JCS_GRAYSCALE || - cinfo->jpeg_color_space == JCS_YCbCr) { + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + case JCS_YCbCr: + case JCS_BG_YCC: cconvert->pub.color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->comp_info[ci].component_needed = FALSE; - } else + break; + case JCS_RGB: + switch (cinfo->color_transform) { + case JCT_NONE: + cconvert->pub.color_convert = rgb_gray_convert; + break; + case JCT_SUBTRACT_GREEN: + cconvert->pub.color_convert = rgb1_gray_convert; + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + build_rgb_y_table(cinfo); + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; case JCS_RGB: cinfo->out_color_components = RGB_PIXELSIZE; - if (cinfo->jpeg_color_space == JCS_YCbCr) { + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + cconvert->pub.color_convert = gray_rgb_convert; + break; + case JCS_YCbCr: cconvert->pub.color_convert = ycc_rgb_convert; build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb_convert; - } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { - cconvert->pub.color_convert = null_convert; + break; + case JCS_BG_YCC: + cconvert->pub.color_convert = ycc_rgb_convert; + build_bg_ycc_rgb_table(cinfo); + break; + case JCS_RGB: + switch (cinfo->color_transform) { + case JCT_NONE: + cconvert->pub.color_convert = rgb_convert; + break; + case JCT_SUBTRACT_GREEN: + cconvert->pub.color_convert = rgb1_rgb_convert; + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + break; + + case JCS_BG_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_BG_RGB) { + switch (cinfo->color_transform) { + case JCT_NONE: + cconvert->pub.color_convert = rgb_convert; + break; + case JCT_SUBTRACT_GREEN: + cconvert->pub.color_convert = rgb1_rgb_convert; + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: cinfo->out_color_components = 4; - if (cinfo->jpeg_color_space == JCS_YCCK) { + switch (cinfo->jpeg_color_space) { + case JCS_YCCK: cconvert->pub.color_convert = ycck_cmyk_convert; build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_CMYK) { + break; + case JCS_CMYK: cconvert->pub.color_convert = null_convert; - } else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; default: diff --git a/uppsrc/plugin/jpg/lib/jdct.h b/uppsrc/plugin/jpg/lib/jdct.h index 484953ce5..5f631f42e 100644 --- a/uppsrc/plugin/jpg/lib/jdct.h +++ b/uppsrc/plugin/jpg/lib/jdct.h @@ -2,23 +2,29 @@ * jdct.h * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file contains common declarations for the forward and * inverse DCT modules. These declarations are private to the DCT managers * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. - * The individual DCT algorithms are kept in separate files to ease + * The individual DCT algorithms are kept in separate files to ease * machine-dependent tuning (e.g., assembly coding). */ /* - * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; - * the DCT is to be performed in-place in that buffer. Type DCTELEM is int - * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT - * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * A forward DCT routine is given a pointer to an input sample array and + * a pointer to a work area of type DCTELEM[]; the DCT is to be performed + * in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32 + * for 12-bit samples. (NOTE: Floating-point DCT implementations use an + * array of type FAST_FLOAT, instead.) + * The input data is to be fetched from the sample array starting at a + * specified column. (Any row offset needed will be applied to the array + * pointer before it is passed to the FDCT code.) + * Note that the number of samples fetched by the FDCT routine is + * DCT_h_scaled_size * DCT_v_scaled_size. * The DCT outputs are returned scaled up by a factor of 8; they therefore * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This * convention improves accuracy in integer implementations and saves some @@ -32,8 +38,12 @@ typedef int DCTELEM; /* 16 or 32 bits is fine */ typedef INT32 DCTELEM; /* must have 32 bits */ #endif -typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); -typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, + JSAMPARRAY sample_data, + JDIMENSION start_col)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, + JSAMPARRAY sample_data, + JDIMENSION start_col)); /* @@ -44,7 +54,7 @@ typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); * sample array starting at a specified column. (Any row offset needed will * be applied to the array pointer before it is passed to the IDCT code.) * Note that the number of samples emitted by the IDCT routine is - * DCT_scaled_size * DCT_scaled_size. + * DCT_h_scaled_size * DCT_v_scaled_size. */ /* typedef inverse_DCT_method_ptr is declared in jpegint.h */ @@ -69,13 +79,16 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could * be quite far out of range if the input data is corrupt, so a bulletproof * range-limiting step is required. We use a mask-and-table-lookup method - * to do the combined operations quickly. See the comments with - * prepare_range_limit_table (in jdmaster.c) for more info. + * to do the combined operations quickly, assuming that MAXJSAMPLE+1 + * is a power of 2. See the comments with prepare_range_limit_table + * (in jdmaster.c) for more info. */ -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) - #define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ +#define RANGE_CENTER (MAXJSAMPLE * 2 + 2) +#define RANGE_SUBSET (RANGE_CENTER - CENTERJSAMPLE) + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit - RANGE_SUBSET) /* Short forms of external names for systems with brain-damaged linkers. */ @@ -84,19 +97,143 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ #define jpeg_fdct_islow jFDislow #define jpeg_fdct_ifast jFDifast #define jpeg_fdct_float jFDfloat +#define jpeg_fdct_7x7 jFD7x7 +#define jpeg_fdct_6x6 jFD6x6 +#define jpeg_fdct_5x5 jFD5x5 +#define jpeg_fdct_4x4 jFD4x4 +#define jpeg_fdct_3x3 jFD3x3 +#define jpeg_fdct_2x2 jFD2x2 +#define jpeg_fdct_1x1 jFD1x1 +#define jpeg_fdct_9x9 jFD9x9 +#define jpeg_fdct_10x10 jFD10x10 +#define jpeg_fdct_11x11 jFD11x11 +#define jpeg_fdct_12x12 jFD12x12 +#define jpeg_fdct_13x13 jFD13x13 +#define jpeg_fdct_14x14 jFD14x14 +#define jpeg_fdct_15x15 jFD15x15 +#define jpeg_fdct_16x16 jFD16x16 +#define jpeg_fdct_16x8 jFD16x8 +#define jpeg_fdct_14x7 jFD14x7 +#define jpeg_fdct_12x6 jFD12x6 +#define jpeg_fdct_10x5 jFD10x5 +#define jpeg_fdct_8x4 jFD8x4 +#define jpeg_fdct_6x3 jFD6x3 +#define jpeg_fdct_4x2 jFD4x2 +#define jpeg_fdct_2x1 jFD2x1 +#define jpeg_fdct_8x16 jFD8x16 +#define jpeg_fdct_7x14 jFD7x14 +#define jpeg_fdct_6x12 jFD6x12 +#define jpeg_fdct_5x10 jFD5x10 +#define jpeg_fdct_4x8 jFD4x8 +#define jpeg_fdct_3x6 jFD3x6 +#define jpeg_fdct_2x4 jFD2x4 +#define jpeg_fdct_1x2 jFD1x2 #define jpeg_idct_islow jRDislow #define jpeg_idct_ifast jRDifast #define jpeg_idct_float jRDfloat +#define jpeg_idct_7x7 jRD7x7 +#define jpeg_idct_6x6 jRD6x6 +#define jpeg_idct_5x5 jRD5x5 #define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_3x3 jRD3x3 #define jpeg_idct_2x2 jRD2x2 #define jpeg_idct_1x1 jRD1x1 +#define jpeg_idct_9x9 jRD9x9 +#define jpeg_idct_10x10 jRD10x10 +#define jpeg_idct_11x11 jRD11x11 +#define jpeg_idct_12x12 jRD12x12 +#define jpeg_idct_13x13 jRD13x13 +#define jpeg_idct_14x14 jRD14x14 +#define jpeg_idct_15x15 jRD15x15 +#define jpeg_idct_16x16 jRD16x16 +#define jpeg_idct_16x8 jRD16x8 +#define jpeg_idct_14x7 jRD14x7 +#define jpeg_idct_12x6 jRD12x6 +#define jpeg_idct_10x5 jRD10x5 +#define jpeg_idct_8x4 jRD8x4 +#define jpeg_idct_6x3 jRD6x3 +#define jpeg_idct_4x2 jRD4x2 +#define jpeg_idct_2x1 jRD2x1 +#define jpeg_idct_8x16 jRD8x16 +#define jpeg_idct_7x14 jRD7x14 +#define jpeg_idct_6x12 jRD6x12 +#define jpeg_idct_5x10 jRD5x10 +#define jpeg_idct_4x8 jRD4x8 +#define jpeg_idct_3x6 jRD3x8 +#define jpeg_idct_2x4 jRD2x4 +#define jpeg_idct_1x2 jRD1x2 #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Extern declarations for the forward and inverse DCT routines. */ -EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); +EXTERN(void) jpeg_fdct_islow + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_ifast + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_float + JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_7x7 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_5x5 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_3x3 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_1x1 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_9x9 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_10x10 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_11x11 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_12x12 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_13x13 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_14x14 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_15x15 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_16x16 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_16x8 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_14x7 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_12x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_10x5 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_8x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x3 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x1 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_8x16 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_7x14 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x12 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_5x10 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x8 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_3x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_1x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_idct_islow JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, @@ -107,15 +244,99 @@ EXTERN(void) jpeg_idct_ifast EXTERN(void) jpeg_idct_float JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_7x7 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_5x5 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_3x3 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x1 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_9x9 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_10x10 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_11x11 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_12x12 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_13x13 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_14x14 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_15x15 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_16x16 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_16x8 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_14x7 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_12x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_10x5 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_8x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x3 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_8x16 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_7x14 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x12 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_5x10 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x8 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_3x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); /* @@ -174,3 +395,23 @@ EXTERN(void) jpeg_idct_1x1 #ifndef MULTIPLY16V16 /* default definition */ #define MULTIPLY16V16(var1,var2) ((var1) * (var2)) #endif + +/* Like RIGHT_SHIFT, but applies to a DCTELEM. + * We assume that int right shift is unsigned if INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif diff --git a/uppsrc/plugin/jpg/lib/jddctmgr.c b/uppsrc/plugin/jpg/lib/jddctmgr.c index 63f563348..b2f5a36d9 100644 --- a/uppsrc/plugin/jpg/lib/jddctmgr.c +++ b/uppsrc/plugin/jpg/lib/jddctmgr.c @@ -1,7 +1,8 @@ /* * jddctmgr.c * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -18,7 +19,6 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy subsystem */ #include "jdct.h" /* Private declarations for DCT subsystem */ @@ -42,15 +42,17 @@ /* Private subobject for this module */ typedef struct { + struct jpeg_inverse_dct pub; /* public fields */ + /* This array contains the IDCT method code that each multiplier table * is currently set up for, or -1 if it's not yet set up. * The actual multiplier tables are pointed to by dct_table in the * per-component comp_info structures. */ int cur_method[MAX_COMPONENTS]; -} idct_controller; +} my_idct_controller; -typedef idct_controller * idct_ptr; +typedef my_idct_controller * my_idct_ptr; /* Allocated multiplier tables: big enough for any supported variant */ @@ -87,8 +89,7 @@ typedef union { METHODDEF(void) start_pass (j_decompress_ptr cinfo) { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - idct_ptr idct = (idct_ptr) lossyd->idct_private; + my_idct_ptr idct = (my_idct_ptr) cinfo->idct; int ci, i; jpeg_component_info *compptr; int method = 0; @@ -98,22 +99,134 @@ start_pass (j_decompress_ptr cinfo) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Select the proper IDCT routine for this component's scaling */ - switch (compptr->codec_data_unit) { + switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED - case 1: + case ((1 << 8) + 1): method_ptr = jpeg_idct_1x1; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ + method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; - case 2: + case ((2 << 8) + 2): method_ptr = jpeg_idct_2x2; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ + method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; - case 4: + case ((3 << 8) + 3): + method_ptr = jpeg_idct_3x3; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 4): method_ptr = jpeg_idct_4x4; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((5 << 8) + 5): + method_ptr = jpeg_idct_5x5; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 6): + method_ptr = jpeg_idct_6x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((7 << 8) + 7): + method_ptr = jpeg_idct_7x7; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((9 << 8) + 9): + method_ptr = jpeg_idct_9x9; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((10 << 8) + 10): + method_ptr = jpeg_idct_10x10; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((11 << 8) + 11): + method_ptr = jpeg_idct_11x11; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((12 << 8) + 12): + method_ptr = jpeg_idct_12x12; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((13 << 8) + 13): + method_ptr = jpeg_idct_13x13; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((14 << 8) + 14): + method_ptr = jpeg_idct_14x14; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((15 << 8) + 15): + method_ptr = jpeg_idct_15x15; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((16 << 8) + 16): + method_ptr = jpeg_idct_16x16; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((16 << 8) + 8): + method_ptr = jpeg_idct_16x8; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((14 << 8) + 7): + method_ptr = jpeg_idct_14x7; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((12 << 8) + 6): + method_ptr = jpeg_idct_12x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((10 << 8) + 5): + method_ptr = jpeg_idct_10x5; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((8 << 8) + 4): + method_ptr = jpeg_idct_8x4; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 3): + method_ptr = jpeg_idct_6x3; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 2): + method_ptr = jpeg_idct_4x2; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((2 << 8) + 1): + method_ptr = jpeg_idct_2x1; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((8 << 8) + 16): + method_ptr = jpeg_idct_8x16; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((7 << 8) + 14): + method_ptr = jpeg_idct_7x14; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 12): + method_ptr = jpeg_idct_6x12; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((5 << 8) + 10): + method_ptr = jpeg_idct_5x10; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 8): + method_ptr = jpeg_idct_4x8; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((3 << 8) + 6): + method_ptr = jpeg_idct_3x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((2 << 8) + 4): + method_ptr = jpeg_idct_2x4; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((1 << 8) + 2): + method_ptr = jpeg_idct_1x2; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; #endif - case DCTSIZE: + case ((DCTSIZE << 8) + DCTSIZE): switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: @@ -139,10 +252,11 @@ start_pass (j_decompress_ptr cinfo) } break; default: - ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->codec_data_unit); + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); break; } - lossyd->inverse_DCT[ci] = method_ptr; + idct->pub.inverse_DCT[ci] = method_ptr; /* Create multiplier table from quant table. * However, we can skip this if the component is uninteresting * or if we already built the table. Also, if no quant table @@ -211,6 +325,7 @@ start_pass (j_decompress_ptr cinfo) * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 1/8. */ FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; int row, col; @@ -224,7 +339,7 @@ start_pass (j_decompress_ptr cinfo) for (col = 0; col < DCTSIZE; col++) { fmtbl[i] = (FLOAT_MULT_TYPE) ((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col]); + aanscalefactor[row] * aanscalefactor[col] * 0.125); i++; } } @@ -246,16 +361,15 @@ start_pass (j_decompress_ptr cinfo) GLOBAL(void) jinit_inverse_dct (j_decompress_ptr cinfo) { - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - idct_ptr idct; + my_idct_ptr idct; int ci; jpeg_component_info *compptr; - idct = (idct_ptr) + idct = (my_idct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(idct_controller)); - lossyd->idct_private = (void *) idct; - lossyd->idct_start_pass = start_pass; + SIZEOF(my_idct_controller)); + cinfo->idct = &idct->pub; + idct->pub.start_pass = start_pass; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { diff --git a/uppsrc/plugin/jpg/lib/jddiffct.c b/uppsrc/plugin/jpg/lib/jddiffct.c deleted file mode 100644 index d9034fd2a..000000000 --- a/uppsrc/plugin/jpg/lib/jddiffct.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * jddiffct.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the [un]difference buffer controller for decompression. - * This controller is the top level of the lossless JPEG decompressor proper. - * The difference buffer lies between the entropy decoding and - * prediction/undifferencing steps. The undifference buffer lies between the - * prediction/undifferencing and scaling steps. - * - * In buffered-image mode, this controller is the interface between - * input-oriented processing and output-oriented processing. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" - - -#ifdef D_LOSSLESS_SUPPORTED - -/* Private buffer controller object */ - -typedef struct { - /* These variables keep track of the current location of the input side. */ - /* cinfo->input_iMCU_row is also used for this. */ - JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ - unsigned int restart_rows_to_go; /* MCU-rows left in this restart interval */ - unsigned int MCU_vert_offset; /* counts MCU rows within iMCU row */ - unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* The output side's location is represented by cinfo->output_iMCU_row. */ - - JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ - JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */ - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* In multi-pass modes, we need a virtual sample array for each component. */ - jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; -#endif -} d_diff_controller; - -typedef d_diff_controller * d_diff_ptr; - -/* Forward declarations */ -METHODDEF(int) decompress_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#ifdef D_MULTISCAN_FILES_SUPPORTED -METHODDEF(int) output_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif - - -LOCAL(void) -start_iMCU_row (j_decompress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row (input side) */ -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - diff->MCU_rows_per_iMCU_row = 1; - } else { - if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) - diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - diff->MCU_ctr = 0; - diff->MCU_vert_offset = 0; -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; - - /* Check that the restart interval is an integer multiple of the number - * of MCU in an MCU-row. - */ - if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) - ERREXIT2(cinfo, JERR_BAD_RESTART, - cinfo->restart_interval, cinfo->MCUs_per_row); - - /* Initialize restart counter */ - diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; - - cinfo->input_iMCU_row = 0; - start_iMCU_row(cinfo); -} - - -/* - * Check for a restart marker & resynchronize decoder, undifferencer. - * Returns FALSE if must suspend. - */ - -METHODDEF(boolean) -process_restart (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; - - if (! (*losslsd->entropy_process_restart) (cinfo)) - return FALSE; - - (*losslsd->predict_process_restart) (cinfo); - - /* Reset restart counter */ - diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; - - return TRUE; -} - - -/* - * Initialize for an output processing pass. - */ - -METHODDEF(void) -start_output_pass (j_decompress_ptr cinfo) -{ - cinfo->output_iMCU_row = 0; -} - - -/* - * Decompress and return some data in the supplied buffer. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Input and output must run in lockstep since we have only a one-MCU buffer. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - -METHODDEF(int) -decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION MCU_count; /* number of MCUs decoded */ - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int comp, ci, yoffset, row, prev_row; - jpeg_component_info *compptr; - - /* Loop to process as much as one whole iMCU row */ - for (yoffset = diff->MCU_vert_offset; (unsigned)yoffset < diff->MCU_rows_per_iMCU_row; - yoffset++) { - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (diff->restart_rows_to_go == 0) - if (! process_restart(cinfo)) - return JPEG_SUSPENDED; - } - - MCU_col_num = diff->MCU_ctr; - /* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */ - MCU_count = - (*losslsd->entropy_decode_mcus) (cinfo, - diff->diff_buf, yoffset, MCU_col_num, - cinfo->MCUs_per_row - MCU_col_num); - if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { - /* Suspension forced; update state counters and exit */ - diff->MCU_vert_offset = yoffset; - diff->MCU_ctr += MCU_count; - return JPEG_SUSPENDED; - } - - /* Account for restart interval (no-op if not using restarts) */ - diff->restart_rows_to_go--; - - /* Completed an MCU row, but perhaps not an iMCU row */ - diff->MCU_ctr = 0; - } - - /* - * Undifference and scale each scanline of the disassembled MCU-row - * separately. We do not process dummy samples at the end of a scanline - * or dummy rows at the end of the image. - */ - for (comp = 0; comp < cinfo->comps_in_scan; comp++) { - compptr = cinfo->cur_comp_info[comp]; - ci = compptr->component_index; - for (row = 0, prev_row = compptr->v_samp_factor - 1; - row < (cinfo->input_iMCU_row == last_iMCU_row ? - compptr->last_row_height : compptr->v_samp_factor); - prev_row = row, row++) { - (*losslsd->predict_undifference[ci]) (cinfo, ci, - diff->diff_buf[ci][row], - diff->undiff_buf[ci][prev_row], - diff->undiff_buf[ci][row], - compptr->width_in_data_units); - (*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row], - output_buf[ci][row], - compptr->width_in_data_units); - } - } - - /* Completed the iMCU row, advance counters for next one. - * - * NB: output_data will increment output_iMCU_row. - * This counter is not needed for the single-pass case - * or the input side of the multi-pass case. - */ - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Dummy consume-input routine for single-pass operation. - */ - -METHODDEF(int) -dummy_consume_data (j_decompress_ptr cinfo) -{ - return JPEG_SUSPENDED; /* Always indicate nothing was done */ -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Consume input data and store it in the full-image sample buffer. - * We read as much as one fully interleaved MCU row ("iMCU" row) per call, - * ie, v_samp_factor rows for each component in the scan. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - */ - -METHODDEF(int) -consume_data (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; -// JDIMENSION MCU_col_num; /* index of current MCU within row */ -// JDIMENSION MCU_count; /* number of MCUs decoded */ -// JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int comp, ci; //, yoffset, row, prev_row; - JSAMPARRAY buffer[MAX_COMPS_IN_SCAN]; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. */ - for (comp = 0; comp < cinfo->comps_in_scan; comp++) { - compptr = cinfo->cur_comp_info[comp]; - ci = compptr->component_index; - buffer[ci] = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, diff->whole_image[ci], - cinfo->input_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - } - - return decompress_data(cinfo, buffer); -} - - -/* - * Output some data from the full-image buffer sample in the multi-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image. - */ - -METHODDEF(int) -output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int ci, samp_rows, row; - JSAMPARRAY buffer; - jpeg_component_info *compptr; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number < cinfo->output_scan_number || - (cinfo->input_scan_number == cinfo->output_scan_number && - cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, diff->whole_image[ci], - cinfo->output_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - - if (cinfo->output_iMCU_row < last_iMCU_row) - samp_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor); - if (samp_rows == 0) samp_rows = compptr->v_samp_factor; - } - - for (row = 0; row < samp_rows; row++) { - MEMCOPY(output_buf[ci][row], buffer[row], - compptr->width_in_data_units * SIZEOF(JSAMPLE)); - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -/* - * Initialize difference buffer controller. - */ - -GLOBAL(void) -jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - d_diff_ptr diff; - int ci; - jpeg_component_info *compptr; - - diff = (d_diff_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(d_diff_controller)); - losslsd->diff_private = (void *) diff; - losslsd->diff_start_input_pass = start_input_pass; - losslsd->pub.start_output_pass = start_output_pass; - - /* Create the [un]difference buffers. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) compptr->v_samp_factor); - diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) compptr->v_samp_factor); - } - - if (need_full_buffer) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* Allocate a full-image virtual array for each component. */ - int access_rows; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - access_rows = compptr->v_samp_factor; - diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_data_units, - (long) compptr->v_samp_factor), - (JDIMENSION) access_rows); - } - losslsd->pub.consume_data = consume_data; - losslsd->pub.decompress_data = output_data; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - losslsd->pub.consume_data = dummy_consume_data; - losslsd->pub.decompress_data = decompress_data; - diff->whole_image[0] = NULL; /* flag for no virtual arrays */ - } -} - -#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jdhuff.c b/uppsrc/plugin/jpg/lib/jdhuff.c index db03294b8..85a98bd3e 100644 --- a/uppsrc/plugin/jpg/lib/jdhuff.c +++ b/uppsrc/plugin/jpg/lib/jdhuff.c @@ -1,20 +1,317 @@ /* * jdhuff.c * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2006-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * - * This file contains Huffman entropy decoding routines which are shared - * by the sequential, progressive and lossless decoders. + * This file contains Huffman entropy decoding routines. + * Both sequential and progressive modes are supported in this single module. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy codec */ -#include "jlossls.h" /* Private declarations for lossless codec */ -#include "jdhuff.h" /* Declarations shared with jd*huff.c */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & BIT_MASK(nbits)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & BIT_MASK(nbits)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + + +/* + * Expanded entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + boolean insufficient_data; /* set TRUE after emitting warning */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Following two fields used only in progressive mode */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ + + /* Following fields used only in sequential mode */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + int coef_limit[D_MAX_BLOCKS_IN_MCU]; +} huff_entropy_decoder; + +typedef huff_entropy_decoder * huff_entropy_ptr; + + +static const int jpeg_zigzag_order[8][8] = { + { 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 } +}; + +static const int jpeg_zigzag_order7[7][7] = { + { 0, 1, 5, 6, 14, 15, 27 }, + { 2, 4, 7, 13, 16, 26, 28 }, + { 3, 8, 12, 17, 25, 29, 38 }, + { 9, 11, 18, 24, 30, 37, 39 }, + { 10, 19, 23, 31, 36, 40, 45 }, + { 20, 22, 32, 35, 41, 44, 46 }, + { 21, 33, 34, 42, 43, 47, 48 } +}; + +static const int jpeg_zigzag_order6[6][6] = { + { 0, 1, 5, 6, 14, 15 }, + { 2, 4, 7, 13, 16, 25 }, + { 3, 8, 12, 17, 24, 26 }, + { 9, 11, 18, 23, 27, 32 }, + { 10, 19, 22, 28, 31, 33 }, + { 20, 21, 29, 30, 34, 35 } +}; + +static const int jpeg_zigzag_order5[5][5] = { + { 0, 1, 5, 6, 14 }, + { 2, 4, 7, 13, 15 }, + { 3, 8, 12, 16, 21 }, + { 9, 11, 17, 20, 22 }, + { 10, 18, 19, 23, 24 } +}; + +static const int jpeg_zigzag_order4[4][4] = { + { 0, 1, 5, 6 }, + { 2, 4, 7, 12 }, + { 3, 8, 11, 13 }, + { 9, 10, 14, 15 } +}; + +static const int jpeg_zigzag_order3[3][3] = { + { 0, 1, 5 }, + { 2, 4, 6 }, + { 3, 7, 8 } +}; + +static const int jpeg_zigzag_order2[2][2] = { + { 0, 1 }, + { 2, 3 } +}; /* @@ -22,7 +319,7 @@ * This routine also performs some validation checks on the table. */ -GLOBAL(void) +LOCAL(void) jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, d_derived_tbl ** pdtbl) { @@ -53,7 +350,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, SIZEOF(d_derived_tbl)); dtbl = *pdtbl; dtbl->pub = htbl; /* fill in back link */ - + /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; @@ -66,10 +363,10 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, } huffsize[p] = 0; numsymbols = p; - + /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ - + code = 0; si = huffsize[0]; p = 0; @@ -129,14 +426,14 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, /* Validate symbols as being reasonable. * For AC tables, we make no check, but accept all byte values 0..255. - * For DC tables, we require the symbols to be in range 0..16. + * For DC tables, we require the symbols to be in range 0..15. * (Tighter bounds could be applied depending on the data depth and mode, * but this is sufficient to ensure safe decoding.) */ if (isDC) { for (i = 0; i < numsymbols; i++) { int sym = htbl->huffval[i]; - if (sym < 0 || sym > 16) + if (sym < 0 || sym > 15) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); } } @@ -145,7 +442,6 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, /* * Out-of-line code for bit fetching. - * See jdhuff.h for info about usage. * Note: current values of get_buffer and bits_left are passed as parameters, * but are returned in the corresponding fields of the state struct. * @@ -165,7 +461,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, #endif -GLOBAL(boolean) +LOCAL(boolean) jpeg_fill_bit_buffer (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, int nbits) @@ -246,14 +542,9 @@ jpeg_fill_bit_buffer (bitread_working_state * state, * We use a nonvolatile flag to ensure that only one warning message * appears per data segment. */ - huffd_common_ptr huffd; - if (cinfo->process == JPROC_LOSSLESS) - huffd = (huffd_common_ptr) ((j_lossless_d_ptr) cinfo->codec)->entropy_private; - else - huffd = (huffd_common_ptr) ((j_lossy_d_ptr) cinfo->codec)->entropy_private; - if (! huffd->insufficient_data) { + if (! ((huff_entropy_ptr) cinfo->entropy)->insufficient_data) { WARNMS(cinfo, JWRN_HIT_MARKER); - huffd->insufficient_data = TRUE; + ((huff_entropy_ptr) cinfo->entropy)->insufficient_data = TRUE; } /* Fill the buffer with zero bits */ get_buffer <<= MIN_GET_BITS - bits_left; @@ -272,11 +563,32 @@ jpeg_fill_bit_buffer (bitread_working_state * state, /* - * Out-of-line code for Huffman code decoding. - * See jdhuff.h for info about usage. + * Figure F.12: extend sign bit. + * On some machines, a shift and sub will be faster than a table lookup. */ -GLOBAL(int) +#ifdef AVOID_TABLES + +#define BIT_MASK(nbits) ((1<<(nbits))-1) +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) - ((1<<(s))-1) : (x)) + +#else + +#define BIT_MASK(nbits) bmask[nbits] +#define HUFF_EXTEND(x,s) ((x) <= bmask[(s) - 1] ? (x) - bmask[s] : (x)) + +static const int bmask[16] = /* bmask[n] is mask for n rightmost bits */ + { 0, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF }; + +#endif /* AVOID_TABLES */ + + +/* + * Out-of-line code for Huffman code decoding. + */ + +LOCAL(int) jpeg_huff_decode (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, d_derived_tbl * htbl, int min_bits) @@ -313,3 +625,930 @@ jpeg_huff_decode (bitread_working_state * state, return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; } + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; +} + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci; + + finish_pass_huff(cinfo); + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int s, k, r; + unsigned int EOBRUN; + int Se, Al; + const int * natural_order; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r != 15) { /* EOBr, run length is 2^r + appended bits */ + if (r) { /* EOBr, r > 0 */ + EOBRUN = 1 << r; + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + EOBRUN--; /* this band is processed at this moment */ + } + break; /* force end-of-band */ + } + k += 15; /* ZRL: skip 15 zeroes in band */ + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, + * although the spec is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int p1, blkn; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + MCU_data[blkn][0][0] |= p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int s, k, r; + unsigned int EOBRUN; + int Se, p1, m1; + const int * natural_order; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->insufficient_data) { + + Se = cinfo->Se; + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + natural_order = cinfo->natural_order; + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + do { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + natural_order[k]; + if (*thiscoef) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + k++; + } while (k <= Se); + } + + if (EOBRUN) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + natural_order[k]; + if (*thiscoef) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } + k++; + } while (k <= Se); + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Decode one MCU's worth of Huffman-compressed coefficients, + * partial blocks. + */ + +METHODDEF(boolean) +decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + const int * natural_order; + int Se, blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + natural_order = cinfo->natural_order; + Se = cinfo->lim_Se; + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * htbl; + register int s, k, r; + int coef_limit, ci; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + htbl = entropy->dc_cur_tbls[blkn]; + HUFF_DECODE(s, br_state, htbl, return FALSE, label1); + + htbl = entropy->ac_cur_tbls[blkn]; + k = 1; + coef_limit = entropy->coef_limit[blkn]; + if (coef_limit) { + /* Convert DC difference to actual value, update last_dc_val */ + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient */ + (*block)[0] = (JCOEF) s; + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (; k < coef_limit; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in natural_order[] will save us + * if k > Se, which could happen if the data is corrupted. + */ + (*block)[natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + goto EndOfBlock; + k += 15; + } + } + } else { + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } + } + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + EndOfBlock: ; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Decode one MCU's worth of Huffman-compressed coefficients, + * full-size blocks. + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * htbl; + register int s, k, r; + int coef_limit, ci; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + htbl = entropy->dc_cur_tbls[blkn]; + HUFF_DECODE(s, br_state, htbl, return FALSE, label1); + + htbl = entropy->ac_cur_tbls[blkn]; + k = 1; + coef_limit = entropy->coef_limit[blkn]; + if (coef_limit) { + /* Convert DC difference to actual value, update last_dc_val */ + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient */ + (*block)[0] = (JCOEF) s; + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (; k < coef_limit; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + goto EndOfBlock; + k += 15; + } + } + } else { + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } + } + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + EndOfBlock: ; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, blkn, tbl, i; + jpeg_component_info * compptr; + + if (cinfo->progressive_mode) { + /* Validate progressive scan parameters */ + if (cinfo->Ss == 0) { + if (cinfo->Se != 0) + goto bad; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) + goto bad; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + goto bad; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Ah-1 != cinfo->Al) + goto bad; + } + if (cinfo->Al > 13) { /* need not check for < 0 */ + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + bad: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + } + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; + int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + } else { + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || + ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && + cinfo->Se != cinfo->lim_Se)) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + /* Select MCU decoding routine */ + /* We retain the hard-coded case for full-size blocks. + * This is not necessary, but it appears that this version is slightly + * more performant in the given implementation. + * With an improved implementation we would prefer a single optimized + * function. + */ + if (cinfo->lim_Se != DCTSIZE2-1) + entropy->pub.decode_mcu = decode_mcu_sub; + else + entropy->pub.decode_mcu = decode_mcu; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->dc_derived_tbls[tbl]); + if (cinfo->lim_Se) { /* AC needs no table when not present */ + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + ci = compptr->DCT_v_scaled_size; + i = compptr->DCT_h_scaled_size; + switch (cinfo->lim_Se) { + case (1*1-1): + entropy->coef_limit[blkn] = 1; + break; + case (2*2-1): + if (ci <= 0 || ci > 2) ci = 2; + if (i <= 0 || i > 2) i = 2; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; + break; + case (3*3-1): + if (ci <= 0 || ci > 3) ci = 3; + if (i <= 0 || i > 3) i = 3; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; + break; + case (4*4-1): + if (ci <= 0 || ci > 4) ci = 4; + if (i <= 0 || i > 4) i = 4; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; + break; + case (5*5-1): + if (ci <= 0 || ci > 5) ci = 5; + if (i <= 0 || i > 5) i = 5; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; + break; + case (6*6-1): + if (ci <= 0 || ci > 6) ci = 6; + if (i <= 0 || i > 6) i = 6; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; + break; + case (7*7-1): + if (ci <= 0 || ci > 7) ci = 7; + if (i <= 0 || i > 7) i = 7; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; + break; + default: + if (ci <= 0 || ci > 8) ci = 8; + if (i <= 0 || i > 8) i = 8; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; + break; + } + } else { + entropy->coef_limit[blkn] = 0; + } + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_decoder)); + cinfo->entropy = &entropy->pub; + entropy->pub.start_pass = start_pass_huff_decoder; + entropy->pub.finish_pass = finish_pass_huff; + + if (cinfo->progressive_mode) { + /* Create progression status table */ + int *coef_bit_ptr, ci; + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + } else { + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } + } +} diff --git a/uppsrc/plugin/jpg/lib/jdhuff.h b/uppsrc/plugin/jpg/lib/jdhuff.h deleted file mode 100644 index 714bd2585..000000000 --- a/uppsrc/plugin/jpg/lib/jdhuff.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * jdhuff.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy decoding routines - * that are shared between the sequential decoder (jdhuff.c), the - * progressive decoder (jdphuff.c) and the lossless decoder (jdlhuff.c). - * No other modules need to see these. - */ - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_d_derived_tbl jMkDDerived -#define jpeg_fill_bit_buffer jFilBitBuf -#define jpeg_huff_decode jHufDecode -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Derived data constructed for each Huffman table */ - -#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ - -typedef struct { - /* Basic tables: (element [0] of each array is unused) */ - INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ - INT32 valoffset[17]; /* huffval[] offset for codes of length k */ - /* valoffset[k] = huffval[] index of 1st symbol of code length k, less - * the smallest code of length k; so given a code of length k, the - * corresponding symbol is huffval[code + valoffset[k]] - */ - - /* Link to public Huffman table (needed only in jpeg_huff_decode) */ - JHUFF_TBL *pub; - - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of - * the input data stream. If the next Huffman code is no more - * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. - */ - int look_nbits[1< 32 bits on your machine, and shifting/masking longs is - * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE - * appropriately should be a win. Unfortunately we can't define the size - * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) - * because not all machines measure sizeof in 8-bit bytes. - */ - -typedef struct { /* Bitreading state saved across MCUs */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ -} bitread_perm_state; - -typedef struct { /* Bitreading working state within an MCU */ - /* Current data source location */ - /* We need a copy, rather than munging the original, in case of suspension */ - const JOCTET * next_input_byte; /* => next byte to read from source */ - size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ - /* Bit input buffer --- note these values are kept in register variables, - * not in this struct, inside the inner loops. - */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ - /* Pointer needed by jpeg_fill_bit_buffer. */ - j_decompress_ptr cinfo; /* back link to decompress master record */ -} bitread_working_state; - -/* Macros to declare and load/save bitread local variables. */ -#define BITREAD_STATE_VARS \ - register bit_buf_type get_buffer; \ - register int bits_left; \ - bitread_working_state br_state - -#define BITREAD_LOAD_STATE(cinfop,permstate) \ - br_state.cinfo = cinfop; \ - br_state.next_input_byte = cinfop->src->next_input_byte; \ - br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ - get_buffer = permstate.get_buffer; \ - bits_left = permstate.bits_left; - -#define BITREAD_SAVE_STATE(cinfop,permstate) \ - cinfop->src->next_input_byte = br_state.next_input_byte; \ - cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ - permstate.get_buffer = get_buffer; \ - permstate.bits_left = bits_left - -/* - * These macros provide the in-line portion of bit fetching. - * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer - * before using GET_BITS, PEEK_BITS, or DROP_BITS. - * The variables get_buffer and bits_left are assumed to be locals, - * but the state struct might not be (jpeg_huff_decode needs this). - * CHECK_BIT_BUFFER(state,n,action); - * Ensure there are N bits in get_buffer; if suspend, take action. - * val = GET_BITS(n); - * Fetch next N bits. - * val = PEEK_BITS(n); - * Fetch next N bits without removing them from the buffer. - * DROP_BITS(n); - * Discard next N bits. - * The value N should be a simple variable, not an expression, because it - * is evaluated multiple times. - */ - -#define CHECK_BIT_BUFFER(state,nbits,action) \ - { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } - -#define GET_BITS(nbits) \ - (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) - -#define PEEK_BITS(nbits) \ - (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) - -#define DROP_BITS(nbits) \ - (bits_left -= (nbits)) - -/* Load up the bit buffer to a depth of at least nbits */ -EXTERN(boolean) jpeg_fill_bit_buffer - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, int nbits)); - - -/* - * Code for extracting next Huffman-coded symbol from input bit stream. - * Again, this is time-critical and we make the main paths be macros. - * - * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits - * without looping. Usually, more than 95% of the Huffman codes will be 8 - * or fewer bits long. The few overlength codes are handled with a loop, - * which need not be inline code. - * - * Notes about the HUFF_DECODE macro: - * 1. Near the end of the data segment, we may fail to get enough bits - * for a lookahead. In that case, we do it the hard way. - * 2. If the lookahead table contains no entry, the next code must be - * more than HUFF_LOOKAHEAD bits long. - * 3. jpeg_huff_decode returns -1 if forced to suspend. - */ - -#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ -{ register int nb, look; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - nb = 1; goto slowlabel; \ - } \ - } \ - look = PEEK_BITS(HUFF_LOOKAHEAD); \ - if ((nb = htbl->look_nbits[look]) != 0) { \ - DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ - } else { \ - nb = HUFF_LOOKAHEAD+1; \ -slowlabel: \ - if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ - { failaction; } \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - } \ -} - -/* Out-of-line case for Huffman code fetching */ -EXTERN(int) jpeg_huff_decode - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, d_derived_tbl * htbl, int min_bits)); - - -/* Common fields between sequential, progressive and lossless Huffman entropy - * decoder master structs. - */ - -#define huffd_common_fields \ - boolean insufficient_data; /* set TRUE after emmitting warning */ \ - /* These fields are loaded into local variables at start of each MCU. \ - * In case of suspension, we exit WITHOUT updating them. \ - */ \ - bitread_perm_state bitstate /* Bit buffer at start of MCU */ - -/* Routines that are to be used by any or all of the entropy decoders are - * declared to receive a pointer to this structure. There are no actual - * instances of huffd_common_struct, only of shuff_entropy_decoder, - * phuff_entropy_decoder and lhuff_entropy_decoder. - */ -struct huffd_common_struct { - huffd_common_fields; /* Fields common to all decoder struct types */ - /* Additional fields follow in an actual shuff_entropy_decoder, - * phuff_entropy_decoder or lhuff_entropy_decoder struct. All four structs - * must agree on these initial fields! (This would be a lot cleaner in C++.) - */ -}; - -typedef struct huffd_common_struct * huffd_common_ptr; diff --git a/uppsrc/plugin/jpg/lib/jdinput.c b/uppsrc/plugin/jpg/lib/jdinput.c index 9ef7243ed..80bdef568 100644 --- a/uppsrc/plugin/jpg/lib/jdinput.c +++ b/uppsrc/plugin/jpg/lib/jdinput.c @@ -1,15 +1,15 @@ /* * jdinput.c * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2002-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains input control logic for the JPEG decompressor. * These routines are concerned with controlling the decompressor's input - * processing (marker reading and coefficient/difference decoding). - * The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c, - * and jdlhuff.c. + * processing (marker reading and coefficient decoding). The actual input + * reading is done in jdmarker.c, jdhuff.c, and jdarith.c. */ #define JPEG_INTERNALS @@ -22,7 +22,7 @@ typedef struct { struct jpeg_input_controller pub; /* public fields */ - boolean inheaders; /* TRUE until first SOS is reached */ + int inheaders; /* Nonzero until first SOS is reached */ } my_input_controller; typedef my_input_controller * my_inputctl_ptr; @@ -36,6 +36,174 @@ METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); * Routines to calculate various quantities related to the size of the image. */ + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + */ + +GLOBAL(void) +jpeg_core_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase. + * This function is used for transcoding and full decompression. + */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom) { + /* Provide 1/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 1; + cinfo->min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 2) { + /* Provide 2/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 2L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 2L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 2; + cinfo->min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 3) { + /* Provide 3/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 3L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 3L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 3; + cinfo->min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 4) { + /* Provide 4/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 4L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 4L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 4; + cinfo->min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 5) { + /* Provide 5/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 5L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 5L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 5; + cinfo->min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 6) { + /* Provide 6/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 6L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 6L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 6; + cinfo->min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 7) { + /* Provide 7/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 7L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 7L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 7; + cinfo->min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 8) { + /* Provide 8/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 8L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 8L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 8; + cinfo->min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 9) { + /* Provide 9/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 9L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 9L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 9; + cinfo->min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 10) { + /* Provide 10/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 10L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 10L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 10; + cinfo->min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 11) { + /* Provide 11/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 11L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 11L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 11; + cinfo->min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 12) { + /* Provide 12/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 12L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 12L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 12; + cinfo->min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 13) { + /* Provide 13/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 13L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 13L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 13; + cinfo->min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 14) { + /* Provide 14/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 14L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 14L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 14; + cinfo->min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 15) { + /* Provide 15/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 15L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 15L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 15; + cinfo->min_DCT_v_scaled_size = 15; + } else { + /* Provide 16/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 16L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 16L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 16; + cinfo->min_DCT_v_scaled_size = 16; + } + + /* Recompute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size; + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size; + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* initial_setup has already initialized DCT_scaled_size, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ +} + + LOCAL(void) initial_setup (j_decompress_ptr cinfo) /* Called once, when first SOS marker is reached */ @@ -48,17 +216,9 @@ initial_setup (j_decompress_ptr cinfo) (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - if (cinfo->process == JPROC_LOSSLESS) { - /* If precision > compiled-in value, we must downscale */ - if (cinfo->data_precision > BITS_IN_JSAMPLE) - WARNMS2(cinfo, JWRN_MUST_DOWNSCALE, - cinfo->data_precision, BITS_IN_JSAMPLE); - } - else { /* Lossy processes */ - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - } + /* Only 8 to 12 bits data precision are supported for DCT based JPEG */ + if (cinfo->data_precision < 8 || cinfo->data_precision > 12) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) @@ -79,23 +239,121 @@ initial_setup (j_decompress_ptr cinfo) compptr->v_samp_factor); } - /* We initialize codec_data_unit and min_codec_data_unit to data_unit. - * In the full decompressor, this will be overridden by jdmaster.c; - * but in the transcoder, jdmaster.c is not used, so we must do it here. + /* Derive block_size, natural_order, and lim_Se */ + if (cinfo->is_baseline || (cinfo->progressive_mode && + cinfo->comps_in_scan)) { /* no pseudo SOS marker */ + cinfo->block_size = DCTSIZE; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + } else + switch (cinfo->Se) { + case (1*1-1): + cinfo->block_size = 1; + cinfo->natural_order = jpeg_natural_order; /* not needed */ + cinfo->lim_Se = cinfo->Se; + break; + case (2*2-1): + cinfo->block_size = 2; + cinfo->natural_order = jpeg_natural_order2; + cinfo->lim_Se = cinfo->Se; + break; + case (3*3-1): + cinfo->block_size = 3; + cinfo->natural_order = jpeg_natural_order3; + cinfo->lim_Se = cinfo->Se; + break; + case (4*4-1): + cinfo->block_size = 4; + cinfo->natural_order = jpeg_natural_order4; + cinfo->lim_Se = cinfo->Se; + break; + case (5*5-1): + cinfo->block_size = 5; + cinfo->natural_order = jpeg_natural_order5; + cinfo->lim_Se = cinfo->Se; + break; + case (6*6-1): + cinfo->block_size = 6; + cinfo->natural_order = jpeg_natural_order6; + cinfo->lim_Se = cinfo->Se; + break; + case (7*7-1): + cinfo->block_size = 7; + cinfo->natural_order = jpeg_natural_order7; + cinfo->lim_Se = cinfo->Se; + break; + case (8*8-1): + cinfo->block_size = 8; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (9*9-1): + cinfo->block_size = 9; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (10*10-1): + cinfo->block_size = 10; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (11*11-1): + cinfo->block_size = 11; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (12*12-1): + cinfo->block_size = 12; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (13*13-1): + cinfo->block_size = 13; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (14*14-1): + cinfo->block_size = 14; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (15*15-1): + cinfo->block_size = 15; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (16*16-1): + cinfo->block_size = 16; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + default: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + break; + } + + /* We initialize DCT_scaled_size and min_DCT_scaled_size to block_size. + * In the full decompressor, + * this will be overridden by jpeg_calc_output_dimensions in jdmaster.c; + * but in the transcoder, + * jpeg_calc_output_dimensions is not used, so we must do it here. */ - cinfo->min_codec_data_unit = cinfo->data_unit; + cinfo->min_DCT_h_scaled_size = cinfo->block_size; + cinfo->min_DCT_v_scaled_size = cinfo->block_size; /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - compptr->codec_data_unit = cinfo->data_unit; - /* Size in data units */ - compptr->width_in_data_units = (JDIMENSION) + compptr->DCT_h_scaled_size = cinfo->block_size; + compptr->DCT_v_scaled_size = cinfo->block_size; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * cinfo->data_unit)); - compptr->height_in_data_units = (JDIMENSION) + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * cinfo->data_unit)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* downsampled_width and downsampled_height will also be overridden by * jdmaster.c if we are doing full decompression. The transcoder library * doesn't use these values, but the calling application might. @@ -116,11 +374,10 @@ initial_setup (j_decompress_ptr cinfo) /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*cinfo->data_unit)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Decide whether file contains multiple scans */ - if (cinfo->comps_in_scan < cinfo->num_components || - cinfo->process == JPROC_PROGRESSIVE) + if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) cinfo->inputctl->has_multiple_scans = TRUE; else cinfo->inputctl->has_multiple_scans = FALSE; @@ -134,73 +391,121 @@ per_scan_setup (j_decompress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; - + if (cinfo->comps_in_scan == 1) { - + /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; - + /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_data_units; - cinfo->MCU_rows_in_scan = compptr->height_in_data_units; - - /* For noninterleaved scan, always one data unit per MCU */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; - compptr->MCU_data_units = 1; - compptr->MCU_sample_width = compptr->codec_data_unit; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_h_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of data unit rows present in the last iMCU row. + * as the number of block rows present in the last iMCU row. */ - tmp = (int) (compptr->height_in_data_units % compptr->v_samp_factor); + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; - + /* Prepare array describing MCU composition */ - cinfo->data_units_in_MCU = 1; + cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; - + } else { - + /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); - + /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*cinfo->data_unit)); + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*cinfo->data_unit)); - - cinfo->data_units_in_MCU = 0; - + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + + cinfo->blocks_in_MCU = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of data units of component in each MCU */ + /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * compptr->codec_data_unit; - /* Figure number of non-dummy data units in last MCU column & row */ - tmp = (int) (compptr->width_in_data_units % compptr->MCU_width); + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_data_units % compptr->MCU_height); + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_data_units; - if (cinfo->data_units_in_MCU + mcublks > D_MAX_DATA_UNITS_IN_MCU) + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci; + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } + + } +} + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; } } @@ -216,8 +521,10 @@ METHODDEF(void) start_input_pass (j_decompress_ptr cinfo) { per_scan_setup(cinfo); - (*cinfo->codec->start_input_pass) (cinfo); - cinfo->inputctl->consume_input = cinfo->codec->consume_data; + latch_quant_tables(cinfo); + (*cinfo->entropy->start_pass) (cinfo); + (*cinfo->coef->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->coef->consume_data; } @@ -230,6 +537,7 @@ start_input_pass (j_decompress_ptr cinfo) METHODDEF(void) finish_input_pass (j_decompress_ptr cinfo) { + (*cinfo->entropy->finish_pass) (cinfo); cinfo->inputctl->consume_input = consume_markers; } @@ -242,6 +550,10 @@ finish_input_pass (j_decompress_ptr cinfo) * The consume_input method pointer points either here or to the * coefficient controller's consume_data routine, depending on whether * we are reading a compressed data segment or inter-segment markers. + * + * Note: This function should NOT return a pseudo SOS marker (with zero + * component number) to the caller. A pseudo marker received by + * read_markers is processed and then skipped for other markers. */ METHODDEF(int) @@ -253,47 +565,50 @@ consume_markers (j_decompress_ptr cinfo) if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ return JPEG_REACHED_EOI; - val = (*cinfo->marker->read_markers) (cinfo); + for (;;) { /* Loop to pass pseudo SOS marker */ + val = (*cinfo->marker->read_markers) (cinfo); - switch (val) { - case JPEG_REACHED_SOS: /* Found SOS */ - if (inputctl->inheaders) { /* 1st SOS */ - initial_setup(cinfo); - /* - * Initialize the decompression codec. We need to do this here so that - * any codec-specific fields and function pointers are available to - * the rest of the library. - */ - jinit_d_codec(cinfo); - inputctl->inheaders = FALSE; - /* Note: start_input_pass must be called by jdmaster.c - * before any more input can be consumed. jdapimin.c is - * responsible for enforcing this sequencing. - */ - } else { /* 2nd or later SOS marker */ - if (! inputctl->pub.has_multiple_scans) - ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ - start_input_pass(cinfo); + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + if (inputctl->inheaders == 1) + initial_setup(cinfo); + if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ + inputctl->inheaders = 2; + break; + } + inputctl->inheaders = 0; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ + break; + start_input_pass(cinfo); + } + return val; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + return val; + case JPEG_SUSPENDED: + return val; + default: + return val; } - break; - case JPEG_REACHED_EOI: /* Found EOI */ - inputctl->pub.eoi_reached = TRUE; - if (inputctl->inheaders) { /* Tables-only datastream, apparently */ - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_NO_SOS); - } else { - /* Prevent infinite loop in coef ctlr's decompress_data routine - * if user set output_scan_number larger than number of scans. - */ - if (cinfo->output_scan_number > cinfo->input_scan_number) - cinfo->output_scan_number = cinfo->input_scan_number; - } - break; - case JPEG_SUSPENDED: - break; } - - return val; } @@ -309,7 +624,7 @@ reset_input_controller (j_decompress_ptr cinfo) inputctl->pub.consume_input = consume_markers; inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; + inputctl->inheaders = 1; /* Reset other modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->marker->reset_marker_reader) (cinfo); @@ -332,7 +647,7 @@ jinit_input_controller (j_decompress_ptr cinfo) inputctl = (my_inputctl_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_input_controller)); - cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + cinfo->inputctl = &inputctl->pub; /* Initialize method pointers */ inputctl->pub.consume_input = consume_markers; inputctl->pub.reset_input_controller = reset_input_controller; @@ -343,5 +658,5 @@ jinit_input_controller (j_decompress_ptr cinfo) */ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; + inputctl->inheaders = 1; } diff --git a/uppsrc/plugin/jpg/lib/jdlhuff.c b/uppsrc/plugin/jpg/lib/jdlhuff.c deleted file mode 100644 index e9359042a..000000000 --- a/uppsrc/plugin/jpg/lib/jdlhuff.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * jdlhuff.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines for lossless JPEG. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" /* Private declarations for lossless codec */ -#include "jdhuff.h" /* Declarations shared with jd*huff.c */ - - -#ifdef D_LOSSLESS_SUPPORTED - -typedef struct { - int ci, yoffset, MCU_width; -} lhd_output_ptr_info; - -/* - * Private entropy decoder object for lossless Huffman decoding. - */ - -typedef struct { - huffd_common_fields; /* Fields shared with other entropy decoders */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - /* Precalculated info set up by start_pass for use in decode_mcus: */ - - /* Pointers to derived tables to be used for each data unit within an MCU */ - d_derived_tbl * cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; - - /* Pointers to the proper output difference row for each group of data units - * within an MCU. For each component, there are Vi groups of Hi data units. - */ - JDIFFROW output_ptr[D_MAX_DATA_UNITS_IN_MCU]; - - /* Number of output pointers in use for the current MCU. This is the sum - * of all Vi in the MCU. - */ - int num_output_ptrs; - - /* Information used for positioning the output pointers within the output - * difference rows. - */ - lhd_output_ptr_info output_ptr_info[D_MAX_DATA_UNITS_IN_MCU]; - - /* Index of the proper output pointer for each data unit within an MCU */ - int output_ptr_index[D_MAX_DATA_UNITS_IN_MCU]; - -} lhuff_entropy_decoder; - -typedef lhuff_entropy_decoder * lhuff_entropy_ptr; - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_lhuff_decoder (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; - int ci, dctbl, sampn, ptrn, yoffset, xoffset; - jpeg_component_info * compptr; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - /* Make sure requested tables are present */ - if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || - cinfo->dc_huff_tbl_ptrs[dctbl] == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, - & entropy->derived_tbls[dctbl]); - } - - /* Precalculate decoding info for each sample in an MCU of this scan */ - for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) { - compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; - ci = compptr->component_index; - for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { - /* Precalculate the setup info for each output pointer */ - entropy->output_ptr_info[ptrn].ci = ci; - entropy->output_ptr_info[ptrn].yoffset = yoffset; - entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width; - for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { - /* Precalculate the output pointer index for each sample */ - entropy->output_ptr_index[sampn] = ptrn; - /* Precalculate which table to use for each sample */ - entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; - } - } - } - entropy->num_output_ptrs = ptrn; - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->insufficient_data = FALSE; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -METHODDEF(boolean) -process_restart (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; -// int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Decode and return nMCU's worth of Huffman-compressed differences. - * Each MCU is also disassembled and placed accordingly in diff_buf. - * - * MCU_col_num specifies the column of the first MCU being requested within - * the MCU-row. This tells us where to position the output row pointers in - * diff_buf. - * - * Returns the number of MCUs decoded. This may be less than nMCU if data - * source requested suspension. In that case no changes have been made to - * permanent state. (Exception: some output differences may already have - * been assigned. This is harmless for this module, since we'll just - * re-assign them on the next call.) - */ - -METHODDEF(JDIMENSION) -decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, - JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; - int mcu_num, sampn, ci, yoffset, MCU_width, ptrn; - BITREAD_STATE_VARS; - - /* Set output pointer locations based on MCU_col_num */ - for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) { - ci = entropy->output_ptr_info[ptrn].ci; - yoffset = entropy->output_ptr_info[ptrn].yoffset; - MCU_width = entropy->output_ptr_info[ptrn].MCU_width; - entropy->output_ptr[ptrn] = - diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); - } - - /* - * If we've run out of data, zero out the buffers and return. - * By resetting the undifferencer, the output samples will be CENTERJSAMPLE. - * - * NB: We should find a way to do this without interacting with the - * undifferencer module directly. - */ - if (entropy->insufficient_data) { - for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) - jzero_far((void FAR *) entropy->output_ptr[ptrn], - nMCU * entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF)); - - (*losslsd->predict_process_restart) (cinfo); - } - - else { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - - /* Outer loop handles the number of MCU requested */ - - for (mcu_num = 0; (unsigned)mcu_num < nMCU; mcu_num++) { - - /* Inner loop handles the samples in the MCU */ - for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { - d_derived_tbl * dctbl = entropy->cur_tbls[sampn]; - register int s, r; - - /* Section H.2.2: decode the sample difference */ - HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1); - if (s) { - if (s == 16) /* special case: always output 32768 */ - s = 32768; - else { /* normal case: fetch subsequent bits */ - CHECK_BIT_BUFFER(br_state, s, return mcu_num); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - } - - /* Output the sample difference */ - *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF) s; - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - } - } - - return nMCU; -} - - -/* - * Module initialization routine for lossless Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_lhuff_decoder (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - lhuff_entropy_ptr entropy; - int i; - - entropy = (lhuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(lhuff_entropy_decoder)); - losslsd->entropy_private = (void *) entropy; - losslsd->entropy_start_pass = start_pass_lhuff_decoder; - losslsd->entropy_process_restart = process_restart; - losslsd->entropy_decode_mcus = decode_mcus; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - } -} - -#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jdlossls.c b/uppsrc/plugin/jpg/lib/jdlossls.c deleted file mode 100644 index 65d3c1d8f..000000000 --- a/uppsrc/plugin/jpg/lib/jdlossls.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * jdlossls.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the control logic for the lossless JPEG decompressor. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" - - -#ifdef D_LOSSLESS_SUPPORTED - -/* - * Compute output image dimensions and related values. - */ - -METHODDEF(void) -calc_output_dimensions (j_decompress_ptr cinfo) -{ - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized codec_data_unit to 1, - * and has computed unscaled downsampled_width and downsampled_height. - */ -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - - (*losslsd->entropy_start_pass) (cinfo); - (*losslsd->predict_start_pass) (cinfo); - (*losslsd->scaler_start_pass) (cinfo); - (*losslsd->diff_start_input_pass) (cinfo); -} - - -/* - * Initialize the lossless decompression codec. - * This is called only once, during master selection. - */ - -GLOBAL(void) -jinit_lossless_d_codec(j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd; - boolean use_c_buffer; - - /* Create subobject in permanent pool */ - losslsd = (j_lossless_d_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(jpeg_lossless_d_codec)); - cinfo->codec = (struct jpeg_d_codec *) losslsd; - - /* Initialize sub-modules */ - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - jinit_lhuff_decoder(cinfo); - } - - /* Undifferencer */ - jinit_undifferencer(cinfo); - - /* Scaler */ - jinit_d_scaler(cinfo); - - use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; - jinit_d_diff_controller(cinfo, use_c_buffer); - - /* Initialize method pointers. - * - * Note: consume_data, start_output_pass and decompress_data are - * assigned in jddiffct.c. - */ - losslsd->pub.calc_output_dimensions = calc_output_dimensions; - losslsd->pub.start_input_pass = start_input_pass; -} - -#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jdlossy.c b/uppsrc/plugin/jpg/lib/jdlossy.c deleted file mode 100644 index 3d7ab4f8e..000000000 --- a/uppsrc/plugin/jpg/lib/jdlossy.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * jdlossy.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the control logic for the lossy JPEG decompressor. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossy.h" - - -/* - * Compute output image dimensions and related values. - */ - -METHODDEF(void) -calc_output_dimensions (j_decompress_ptr cinfo) -{ -#ifdef IDCT_SCALING_SUPPORTED - int ci; - jpeg_component_info *compptr; - - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * 8 <= cinfo->scale_denom) { - /* Provide 1/8 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 8L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 8L); - cinfo->min_codec_data_unit = 1; - } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { - /* Provide 1/4 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 4L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 4L); - cinfo->min_codec_data_unit = 2; - } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { - /* Provide 1/2 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 2L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 2L); - cinfo->min_codec_data_unit = 4; - } else { - /* Provide 1/1 scaling */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - cinfo->min_codec_data_unit = DCTSIZE; - } - /* In selecting the actual DCT scaling for each component, we try to - * scale up the chroma components via IDCT scaling rather than upsampling. - * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code assumes that the supported DCT scalings are powers of 2. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - int ssize = cinfo->min_codec_data_unit; - while (ssize < DCTSIZE && - (compptr->h_samp_factor * ssize * 2 <= - cinfo->max_h_samp_factor * cinfo->min_codec_data_unit) && - (compptr->v_samp_factor * ssize * 2 <= - cinfo->max_v_samp_factor * cinfo->min_codec_data_unit)) { - ssize = ssize * 2; - } - compptr->codec_data_unit = ssize; - } - - /* Recompute downsampled dimensions of components; - * application needs to know these if using raw downsampled data. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Size in samples, after IDCT scaling */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * - (long) (compptr->h_samp_factor * compptr->codec_data_unit), - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * - (long) (compptr->v_samp_factor * compptr->codec_data_unit), - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized codec_data_unit to DCTSIZE, - * and has computed unscaled downsampled_width and downsampled_height. - */ - -#endif /* IDCT_SCALING_SUPPORTED */ -} - - -/* - * Save away a copy of the Q-table referenced by each component present - * in the current scan, unless already saved during a prior scan. - * - * In a multiple-scan JPEG file, the encoder could assign different components - * the same Q-table slot number, but change table definitions between scans - * so that each component uses a different Q-table. (The IJG encoder is not - * currently capable of doing this, but other encoders might.) Since we want - * to be able to dequantize all the components at the end of the file, this - * means that we have to save away the table actually used for each component. - * We do this by copying the table at the start of the first scan containing - * the component. - * The JPEG spec prohibits the encoder from changing the contents of a Q-table - * slot between scans of a component using that slot. If the encoder does so - * anyway, this decoder will simply use the Q-table values that were current - * at the start of the first scan for the component. - * - * The decompressor output side looks only at the saved quant tables, - * not at the current Q-table slots. - */ - -LOCAL(void) -latch_quant_tables (j_decompress_ptr cinfo) -{ - int ci, qtblno; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* No work if we already saved Q-table for this component */ - if (compptr->quant_table != NULL) - continue; - /* Make sure specified quantization table is present */ - qtblno = compptr->quant_tbl_no; - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - /* OK, save away the quantization table */ - qtbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(JQUANT_TBL)); - MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); - compptr->quant_table = qtbl; - } -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - - latch_quant_tables(cinfo); - (*lossyd->entropy_start_pass) (cinfo); - (*lossyd->coef_start_input_pass) (cinfo); -} - - -/* - * Initialize for an output processing pass. - */ - -METHODDEF(void) -start_output_pass (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - - (*lossyd->idct_start_pass) (cinfo); - (*lossyd->coef_start_output_pass) (cinfo); -} - -/* - * Initialize the lossy decompression codec. - * This is called only once, during master selection. - */ - -GLOBAL(void) -jinit_lossy_d_codec (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd; - boolean use_c_buffer; - - /* Create subobject in permanent pool */ - lossyd = (j_lossy_d_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(jpeg_lossy_d_codec)); - cinfo->codec = (struct jpeg_d_codec *) lossyd; - - /* Initialize sub-modules */ - - /* Inverse DCT */ - jinit_inverse_dct(cinfo); - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->process == JPROC_PROGRESSIVE) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_shuff_decoder(cinfo); - } - - use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; - jinit_d_coef_controller(cinfo, use_c_buffer); - - /* Initialize method pointers. - * - * Note: consume_data and decompress_data are assigned in jdcoefct.c. - */ - lossyd->pub.calc_output_dimensions = calc_output_dimensions; - lossyd->pub.start_input_pass = start_input_pass; - lossyd->pub.start_output_pass = start_output_pass; -} diff --git a/uppsrc/plugin/jpg/lib/jdmainct.c b/uppsrc/plugin/jpg/lib/jdmainct.c index c3daa47aa..7ced4386b 100644 --- a/uppsrc/plugin/jpg/lib/jdmainct.c +++ b/uppsrc/plugin/jpg/lib/jdmainct.c @@ -1,7 +1,8 @@ /* * jdmainct.c * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2012 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -26,18 +27,18 @@ * rescaling, and doing this in an efficient fashion is a bit tricky. * * Postprocessor input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit) - * sample rows of each component. (We require codec_data_unit values to be - * chosen such that these numbers are integers. In practice codec_data_unit + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. (We require DCT_scaled_size values to be + * chosen such that these numbers are integers. In practice DCT_scaled_size * values will likely be powers of two, so we actually have the stronger - * condition that codec_data_unit / min_codec_data_unit is an integer.) + * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) * Upsampling will typically produce max_v_samp_factor pixel rows from each * row group (times any additional scale factor that the upsampler is * applying). * - * The decompression codec will deliver data to us one iMCU row at a time; - * each iMCU row contains v_samp_factor * codec_data_unit sample rows, or - * exactly min_codec_data_unit row groups. (This amount of data corresponds + * The coefficient controller will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or + * exactly min_DCT_scaled_size row groups. (This amount of data corresponds * to one row of MCUs when the image is fully interleaved.) Note that the * number of sample rows varies across components, but the number of row * groups does not. Some garbage sample rows may be included in the last iMCU @@ -64,7 +65,7 @@ * supporting arbitrary output rescaling might wish for more than one row * group of context when shrinking the image; tough, we don't handle that. * (This is justified by the assumption that downsizing will be handled mostly - * by adjusting the codec_data_unit values, so that the actual scale factor at + * by adjusting the DCT_scaled_size values, so that the actual scale factor at * the upsample step needn't be much less than one.) * * To provide the desired context, we have to retain the last two row groups @@ -74,7 +75,7 @@ * We could do this most simply by copying data around in our buffer, but * that'd be very slow. We can avoid copying any data by creating a rather * strange pointer structure. Here's how it works. We allocate a workspace - * consisting of M+2 row groups (where M = min_codec_data_unit is the number + * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number * of row groups per iMCU row). We create two sets of redundant pointers to * the workspace. Labeling the physical row groups 0 to M+1, the synthesized * pointer lists look like this: @@ -99,11 +100,11 @@ * the first or last sample row as necessary (this is cheaper than copying * sample rows around). * - * This scheme breaks down if M < 2, ie, min_codec_data_unit is 1. In that + * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that * situation each iMCU row provides only one row group so the buffering logic * must be different (eg, we must read two iMCU rows before we can emit the * first row group). For now, we simply do not support providing context - * rows when min_codec_data_unit is 1. That combination seems unlikely to + * rows when min_DCT_scaled_size is 1. That combination seems unlikely to * be worth providing --- if someone wants a 1/8th-size preview, they probably * want it quick and dirty, so a context-free upsampler is sufficient. */ @@ -159,24 +160,24 @@ alloc_funny_pointers (j_decompress_ptr cinfo) * This is done only once, not once per pass. */ { - my_main_ptr main_ = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci, rgroup; - int M = cinfo->min_codec_data_unit; + int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf; /* Get top-level space for component array pointers. * We alloc both arrays with one call to save a few cycles. */ - main_->xbuffer[0] = (JSAMPIMAGE) + mainp->xbuffer[0] = (JSAMPIMAGE) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); - main_->xbuffer[1] = main_->xbuffer[0] + cinfo->num_components; + mainp->xbuffer[1] = mainp->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / - cinfo->min_codec_data_unit; /* height of a row group of component */ + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ /* Get space for pointer lists --- M+4 row groups in each list. * We alloc both pointer lists with one call to save a few cycles. */ @@ -184,9 +185,9 @@ alloc_funny_pointers (j_decompress_ptr cinfo) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); xbuf += rgroup; /* want one row group at negative offsets */ - main_->xbuffer[0][ci] = xbuf; + mainp->xbuffer[0][ci] = xbuf; xbuf += rgroup * (M + 4); - main_->xbuffer[1][ci] = xbuf; + mainp->xbuffer[1][ci] = xbuf; } } @@ -200,20 +201,20 @@ make_funny_pointers (j_decompress_ptr cinfo) * This will be repeated at the beginning of each pass. */ { - my_main_ptr main_ = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci, i, rgroup; - int M = cinfo->min_codec_data_unit; + int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY buf, xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / - cinfo->min_codec_data_unit; /* height of a row group of component */ - xbuf0 = main_->xbuffer[0][ci]; - xbuf1 = main_->xbuffer[1][ci]; + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ + xbuf0 = mainp->xbuffer[0][ci]; + xbuf1 = mainp->xbuffer[1][ci]; /* First copy the workspace pointers as-is */ - buf = main_->buffer[ci]; + buf = mainp->buffer[ci]; for (i = 0; i < rgroup * (M + 2); i++) { xbuf0[i] = xbuf1[i] = buf[i]; } @@ -240,18 +241,18 @@ set_wraparound_pointers (j_decompress_ptr cinfo) * This changes the pointer list state from top-of-image to the normal state. */ { - my_main_ptr main_ = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci, i, rgroup; - int M = cinfo->min_codec_data_unit; + int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / - cinfo->min_codec_data_unit; /* height of a row group of component */ - xbuf0 = main_->xbuffer[0][ci]; - xbuf1 = main_->xbuffer[1][ci]; + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ + xbuf0 = mainp->xbuffer[0][ci]; + xbuf1 = mainp->xbuffer[1][ci]; for (i = 0; i < rgroup; i++) { xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; @@ -269,7 +270,7 @@ set_bottom_pointers (j_decompress_ptr cinfo) * Also sets rowgroups_avail to indicate number of nondummy row groups in row. */ { - my_main_ptr main_ = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci, i, rgroup, iMCUheight, rows_left; jpeg_component_info *compptr; JSAMPARRAY xbuf; @@ -277,8 +278,8 @@ set_bottom_pointers (j_decompress_ptr cinfo) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Count sample rows in one iMCU row and in one row group */ - iMCUheight = compptr->v_samp_factor * compptr->codec_data_unit; - rgroup = iMCUheight / cinfo->min_codec_data_unit; + iMCUheight = compptr->v_samp_factor * compptr->DCT_v_scaled_size; + rgroup = iMCUheight / cinfo->min_DCT_v_scaled_size; /* Count nondummy sample rows remaining for this component */ rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); if (rows_left == 0) rows_left = iMCUheight; @@ -286,12 +287,12 @@ set_bottom_pointers (j_decompress_ptr cinfo) * so we need only do it once. */ if (ci == 0) { - main_->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + mainp->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); } /* Duplicate the last real sample row rgroup*2 times; this pads out the * last partial rowgroup and ensures at least one full rowgroup of context. */ - xbuf = main_->xbuffer[main_->whichptr][ci]; + xbuf = mainp->xbuffer[mainp->whichptr][ci]; for (i = 0; i < rgroup * 2; i++) { xbuf[rows_left + i] = xbuf[rows_left-1]; } @@ -306,27 +307,27 @@ set_bottom_pointers (j_decompress_ptr cinfo) METHODDEF(void) start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { - my_main_ptr main_ = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->upsample->need_context_rows) { - main_->pub.process_data = process_data_context_main; + mainp->pub.process_data = process_data_context_main; make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ - main_->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ - main_->context_state = CTX_PREPARE_FOR_IMCU; - main_->iMCU_row_ctr = 0; + mainp->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + mainp->context_state = CTX_PREPARE_FOR_IMCU; + mainp->iMCU_row_ctr = 0; } else { /* Simple case with no context needed */ - main_->pub.process_data = process_data_simple_main; + mainp->pub.process_data = process_data_simple_main; } - main_->buffer_full = FALSE; /* Mark buffer empty */ - main_->rowgroup_ctr = 0; + mainp->buffer_full = FALSE; /* Mark buffer empty */ + mainp->rowgroup_ctr = 0; break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_CRANK_DEST: /* For last pass of 2-pass quantization, just crank the postprocessor */ - main_->pub.process_data = process_data_crank_post; + mainp->pub.process_data = process_data_crank_post; break; #endif default: @@ -346,32 +347,32 @@ process_data_simple_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { - my_main_ptr main_ = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; JDIMENSION rowgroups_avail; - /* Read input data if we haven't filled the main_ buffer yet */ - if (! main_->buffer_full) { - if (! (*cinfo->codec->decompress_data) (cinfo, main_->buffer)) + /* Read input data if we haven't filled the main buffer yet */ + if (! mainp->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, mainp->buffer)) return; /* suspension forced, can do nothing more */ - main_->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + mainp->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ } - /* There are always min_codec_data_unit row groups in an iMCU row. */ - rowgroups_avail = (JDIMENSION) cinfo->min_codec_data_unit; + /* There are always min_DCT_scaled_size row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_DCT_v_scaled_size; /* Note: at the bottom of the image, we may pass extra garbage row groups * to the postprocessor. The postprocessor has to check for bottom * of image anyway (at row resolution), so no point in us doing it too. */ /* Feed the postprocessor */ - (*cinfo->post->post_process_data) (cinfo, main_->buffer, - &main_->rowgroup_ctr, rowgroups_avail, + (*cinfo->post->post_process_data) (cinfo, mainp->buffer, + &mainp->rowgroup_ctr, rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ - if (main_->rowgroup_ctr >= rowgroups_avail) { - main_->buffer_full = FALSE; - main_->rowgroup_ctr = 0; + if (mainp->rowgroup_ctr >= rowgroups_avail) { + mainp->buffer_full = FALSE; + mainp->rowgroup_ctr = 0; } } @@ -386,15 +387,15 @@ process_data_context_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { - my_main_ptr main_ = (my_main_ptr) cinfo->main; + my_main_ptr mainp = (my_main_ptr) cinfo->main; - /* Read input data if we haven't filled the main_ buffer yet */ - if (! main_->buffer_full) { - if (! (*cinfo->codec->decompress_data) (cinfo, - main_->xbuffer[main_->whichptr])) + /* Read input data if we haven't filled the main buffer yet */ + if (! mainp->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, + mainp->xbuffer[mainp->whichptr])) return; /* suspension forced, can do nothing more */ - main_->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - main_->iMCU_row_ctr++; /* count rows received */ + mainp->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + mainp->iMCU_row_ctr++; /* count rows received */ } /* Postprocessor typically will not swallow all the input data it is handed @@ -402,47 +403,47 @@ process_data_context_main (j_decompress_ptr cinfo, * to exit and restart. This switch lets us keep track of how far we got. * Note that each case falls through to the next on successful completion. */ - switch (main_->context_state) { + switch (mainp->context_state) { case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, main_->xbuffer[main_->whichptr], - &main_->rowgroup_ctr, main_->rowgroups_avail, + (*cinfo->post->post_process_data) (cinfo, mainp->xbuffer[mainp->whichptr], + &mainp->rowgroup_ctr, mainp->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); - if (main_->rowgroup_ctr < main_->rowgroups_avail) + if (mainp->rowgroup_ctr < mainp->rowgroups_avail) return; /* Need to suspend */ - main_->context_state = CTX_PREPARE_FOR_IMCU; + mainp->context_state = CTX_PREPARE_FOR_IMCU; if (*out_row_ctr >= out_rows_avail) return; /* Postprocessor exactly filled output buf */ /*FALLTHROUGH*/ case CTX_PREPARE_FOR_IMCU: /* Prepare to process first M-1 row groups of this iMCU row */ - main_->rowgroup_ctr = 0; - main_->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit - 1); + mainp->rowgroup_ctr = 0; + mainp->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size - 1); /* Check for bottom of image: if so, tweak pointers to "duplicate" * the last sample row, and adjust rowgroups_avail to ignore padding rows. */ - if (main_->iMCU_row_ctr == cinfo->total_iMCU_rows) + if (mainp->iMCU_row_ctr == cinfo->total_iMCU_rows) set_bottom_pointers(cinfo); - main_->context_state = CTX_PROCESS_IMCU; + mainp->context_state = CTX_PROCESS_IMCU; /*FALLTHROUGH*/ case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, main_->xbuffer[main_->whichptr], - &main_->rowgroup_ctr, main_->rowgroups_avail, + (*cinfo->post->post_process_data) (cinfo, mainp->xbuffer[mainp->whichptr], + &mainp->rowgroup_ctr, mainp->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); - if (main_->rowgroup_ctr < main_->rowgroups_avail) + if (mainp->rowgroup_ctr < mainp->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ - if (main_->iMCU_row_ctr == 1) + if (mainp->iMCU_row_ctr == 1) set_wraparound_pointers(cinfo); /* Prepare to load new iMCU row using other xbuffer list */ - main_->whichptr ^= 1; /* 0=>1 or 1=>0 */ - main_->buffer_full = FALSE; + mainp->whichptr ^= 1; /* 0=>1 or 1=>0 */ + mainp->buffer_full = FALSE; /* Still need to process last row group of this iMCU row, */ /* which is saved at index M+1 of the other xbuffer */ - main_->rowgroup_ctr = (JDIMENSION) (cinfo->min_codec_data_unit + 1); - main_->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit + 2); - main_->context_state = CTX_POSTPONED_ROW; + mainp->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 1); + mainp->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 2); + mainp->context_state = CTX_POSTPONED_ROW; } } @@ -475,15 +476,15 @@ process_data_crank_post (j_decompress_ptr cinfo, GLOBAL(void) jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { - my_main_ptr main_; + my_main_ptr mainp; int ci, rgroup, ngroups; jpeg_component_info *compptr; - main_ = (my_main_ptr) + mainp = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_d_main_controller *) main_; - main_->pub.start_pass = start_pass_main; + cinfo->main = &mainp->pub; + mainp->pub.start_pass = start_pass_main; if (need_full_buffer) /* shouldn't happen */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); @@ -492,21 +493,21 @@ jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) * ngroups is the number of row groups we need. */ if (cinfo->upsample->need_context_rows) { - if (cinfo->min_codec_data_unit < 2) /* unsupported, see comments above */ + if (cinfo->min_DCT_v_scaled_size < 2) /* unsupported, see comments above */ ERREXIT(cinfo, JERR_NOTIMPL); alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ - ngroups = cinfo->min_codec_data_unit + 2; + ngroups = cinfo->min_DCT_v_scaled_size + 2; } else { - ngroups = cinfo->min_codec_data_unit; + ngroups = cinfo->min_DCT_v_scaled_size; } for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / - cinfo->min_codec_data_unit; /* height of a row group of component */ - main_->buffer[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_data_units * compptr->codec_data_unit, - (JDIMENSION) (rgroup * ngroups)); + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ + mainp->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), + (JDIMENSION) (rgroup * ngroups)); } } diff --git a/uppsrc/plugin/jpg/lib/jdmarker.c b/uppsrc/plugin/jpg/lib/jdmarker.c index a4bce4f7a..b1faf88fb 100644 --- a/uppsrc/plugin/jpg/lib/jdmarker.c +++ b/uppsrc/plugin/jpg/lib/jdmarker.c @@ -2,6 +2,7 @@ * jdmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2009-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -76,6 +77,7 @@ typedef enum { /* JPEG marker codes */ M_APP15 = 0xef, M_JPG0 = 0xf0, + M_JPG8 = 0xf8, M_JPG13 = 0xfd, M_COM = 0xfe, @@ -198,7 +200,7 @@ get_soi (j_decompress_ptr cinfo) /* Process an SOI marker */ { int i; - + TRACEMS(cinfo, 1, JTRC_SOI); if (cinfo->marker->saw_SOI) @@ -216,6 +218,7 @@ get_soi (j_decompress_ptr cinfo) /* Set initial assumptions for colorspace etc */ cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->color_transform = JCT_NONE; cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ cinfo->saw_JFIF_marker = FALSE; @@ -234,17 +237,17 @@ get_soi (j_decompress_ptr cinfo) LOCAL(boolean) -get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith, - int data_unit) +get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, + boolean is_arith) /* Process a SOFn marker */ { INT32 length; - int c, ci; + int c, ci, i; jpeg_component_info * compptr; INPUT_VARS(cinfo); - cinfo->data_unit = data_unit; - cinfo->process = process; + cinfo->is_baseline = is_baseline; + cinfo->progressive_mode = is_prog; cinfo->arith_code = is_arith; INPUT_2BYTES(cinfo, length, return FALSE); @@ -266,8 +269,8 @@ get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith, /* We don't support files in which the image height is initially specified */ /* as 0 and is later redefined by DNL. As long as we have to check that, */ /* might as well have a general sanity check. */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0) + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || + cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); if (length != (cinfo->num_components * 3)) @@ -278,10 +281,26 @@ get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith, ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * SIZEOF(jpeg_component_info)); - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + for (ci = 0; ci < cinfo->num_components; ci++) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Check to see whether component id has already been seen */ + /* (in violation of the spec, but unfortunately seen in some */ + /* files). If so, create "fake" component id equal to the */ + /* max id seen so far + 1. */ + for (i = 0, compptr = cinfo->comp_info; i < ci; i++, compptr++) { + if (c == compptr->component_id) { + compptr = cinfo->comp_info; + c = compptr->component_id; + compptr++; + for (i = 1; i < ci; i++, compptr++) { + if (compptr->component_id > c) c = compptr->component_id; + } + c++; + break; + } + } + compptr->component_id = c; compptr->component_index = ci; - INPUT_BYTE(cinfo, compptr->component_id, return FALSE); INPUT_BYTE(cinfo, c, return FALSE); compptr->h_samp_factor = (c >> 4) & 15; compptr->v_samp_factor = (c ) & 15; @@ -304,12 +323,12 @@ get_sos (j_decompress_ptr cinfo) /* Process a SOS marker */ { INT32 length; - int i, ci, n, c, cc; + int c, ci, i, n; jpeg_component_info * compptr; INPUT_VARS(cinfo); if (! cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOS_NO_SOF); + ERREXITS(cinfo, JERR_SOF_BEFORE, "SOS"); INPUT_2BYTES(cinfo, length, return FALSE); @@ -317,7 +336,9 @@ get_sos (j_decompress_ptr cinfo) TRACEMS1(cinfo, 1, JTRC_SOS, n); - if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + if (length != (n * 2 + 6) || n > MAX_COMPS_IN_SCAN || + (n == 0 && !cinfo->progressive_mode)) + /* pseudo SOS marker only allowed in progressive mode */ ERREXIT(cinfo, JERR_BAD_LENGTH); cinfo->comps_in_scan = n; @@ -325,24 +346,41 @@ get_sos (j_decompress_ptr cinfo) /* Collect the component-spec parameters */ for (i = 0; i < n; i++) { - INPUT_BYTE(cinfo, cc, return FALSE); INPUT_BYTE(cinfo, c, return FALSE); + /* Detect the case where component id's are not unique, and, if so, */ + /* create a fake component id using the same logic as in get_sof. */ + /* Note: This also ensures that all of the SOF components are */ + /* referenced in the single scan case, which prevents access to */ + /* uninitialized memory in later decoding stages. */ + for (ci = 0; ci < i; ci++) { + if (c == cinfo->cur_comp_info[ci]->component_id) { + c = cinfo->cur_comp_info[0]->component_id; + for (ci = 1; ci < i; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (compptr->component_id > c) c = compptr->component_id; + } + c++; + break; + } + } + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - if (cc == compptr->component_id) + if (c == compptr->component_id) goto id_found; } - ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, c); id_found: cinfo->cur_comp_info[i] = compptr; + INPUT_BYTE(cinfo, c, return FALSE); compptr->dc_tbl_no = (c >> 4) & 15; compptr->ac_tbl_no = (c ) & 15; - TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, compptr->component_id, compptr->dc_tbl_no, compptr->ac_tbl_no); } @@ -361,8 +399,8 @@ get_sos (j_decompress_ptr cinfo) /* Prepare to scan data & restart markers */ cinfo->marker->next_restart_num = 0; - /* Count another SOS marker */ - cinfo->input_scan_number++; + /* Count another (non-pseudo) SOS marker */ + if (n) cinfo->input_scan_number++; INPUT_SYNC(cinfo); return TRUE; @@ -381,7 +419,7 @@ get_dac (j_decompress_ptr cinfo) INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; - + while (length > 0) { INPUT_BYTE(cinfo, index, return FALSE); INPUT_BYTE(cinfo, val, return FALSE); @@ -430,12 +468,12 @@ get_dht (j_decompress_ptr cinfo) INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; - + while (length > 16) { INPUT_BYTE(cinfo, index, return FALSE); TRACEMS1(cinfo, 1, JTRC_DHT, index); - + bits[0] = 0; count = 0; for (i = 1; i <= 16; i++) { @@ -458,6 +496,8 @@ get_dht (j_decompress_ptr cinfo) if (count > 256 || ((INT32) count) > length) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + MEMZERO(huffval, SIZEOF(huffval)); /* pre-zero array for later copy */ + for (i = 0; i < count; i++) INPUT_BYTE(cinfo, huffval[i], return FALSE); @@ -475,7 +515,7 @@ get_dht (j_decompress_ptr cinfo) if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); } @@ -492,16 +532,18 @@ LOCAL(boolean) get_dqt (j_decompress_ptr cinfo) /* Process a DQT marker */ { - INT32 length; - int n, i, prec; + INT32 length, count, i; + int n, prec; unsigned int tmp; JQUANT_TBL *quant_ptr; + const int *natural_order; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { + length--; INPUT_BYTE(cinfo, n, return FALSE); prec = n >> 4; n &= 0x0F; @@ -510,18 +552,48 @@ get_dqt (j_decompress_ptr cinfo) if (n >= NUM_QUANT_TBLS) ERREXIT1(cinfo, JERR_DQT_INDEX, n); - + if (cinfo->quant_tbl_ptrs[n] == NULL) cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); quant_ptr = cinfo->quant_tbl_ptrs[n]; - for (i = 0; i < DCTSIZE2; i++) { + if (prec) { + if (length < DCTSIZE2 * 2) { + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length >> 1; + } else + count = DCTSIZE2; + } else { + if (length < DCTSIZE2) { + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length; + } else + count = DCTSIZE2; + } + + switch (count) { + case (2*2): natural_order = jpeg_natural_order2; break; + case (3*3): natural_order = jpeg_natural_order3; break; + case (4*4): natural_order = jpeg_natural_order4; break; + case (5*5): natural_order = jpeg_natural_order5; break; + case (6*6): natural_order = jpeg_natural_order6; break; + case (7*7): natural_order = jpeg_natural_order7; break; + default: natural_order = jpeg_natural_order; break; + } + + for (i = 0; i < count; i++) { if (prec) INPUT_2BYTES(cinfo, tmp, return FALSE); else INPUT_BYTE(cinfo, tmp, return FALSE); /* We convert the zigzag-order table to natural array order. */ - quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + quant_ptr->quantval[natural_order[i]] = (UINT16) tmp; } if (cinfo->err->trace_level >= 2) { @@ -534,8 +606,8 @@ get_dqt (j_decompress_ptr cinfo) } } - length -= DCTSIZE2+1; - if (prec) length -= DCTSIZE2; + length -= count; + if (prec) length -= count; } if (length != 0) @@ -555,7 +627,7 @@ get_dri (j_decompress_ptr cinfo) INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); - + if (length != 4) ERREXIT(cinfo, JERR_BAD_LENGTH); @@ -570,6 +642,68 @@ get_dri (j_decompress_ptr cinfo) } +LOCAL(boolean) +get_lse (j_decompress_ptr cinfo) +/* Process an LSE marker */ +{ + INT32 length; + unsigned int tmp; + int cid; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXITS(cinfo, JERR_SOF_BEFORE, "LSE"); + + if (cinfo->num_components < 3) goto bad; + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 24) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_BYTE(cinfo, tmp, return FALSE); + if (tmp != 0x0D) /* ID inverse transform specification */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + INPUT_2BYTES(cinfo, tmp, return FALSE); + if (tmp != MAXJSAMPLE) goto bad; /* MAXTRANS */ + INPUT_BYTE(cinfo, tmp, return FALSE); + if (tmp != 3) goto bad; /* Nt=3 */ + INPUT_BYTE(cinfo, cid, return FALSE); + if (cid != cinfo->comp_info[1].component_id) goto bad; + INPUT_BYTE(cinfo, cid, return FALSE); + if (cid != cinfo->comp_info[0].component_id) goto bad; + INPUT_BYTE(cinfo, cid, return FALSE); + if (cid != cinfo->comp_info[2].component_id) goto bad; + INPUT_BYTE(cinfo, tmp, return FALSE); + if (tmp != 0x80) goto bad; /* F1: CENTER1=1, NORM1=0 */ + INPUT_2BYTES(cinfo, tmp, return FALSE); + if (tmp != 0) goto bad; /* A(1,1)=0 */ + INPUT_2BYTES(cinfo, tmp, return FALSE); + if (tmp != 0) goto bad; /* A(1,2)=0 */ + INPUT_BYTE(cinfo, tmp, return FALSE); + if (tmp != 0) goto bad; /* F2: CENTER2=0, NORM2=0 */ + INPUT_2BYTES(cinfo, tmp, return FALSE); + if (tmp != 1) goto bad; /* A(2,1)=1 */ + INPUT_2BYTES(cinfo, tmp, return FALSE); + if (tmp != 0) goto bad; /* A(2,2)=0 */ + INPUT_BYTE(cinfo, tmp, return FALSE); + if (tmp != 0) goto bad; /* F3: CENTER3=0, NORM3=0 */ + INPUT_2BYTES(cinfo, tmp, return FALSE); + if (tmp != 1) goto bad; /* A(3,1)=1 */ + INPUT_2BYTES(cinfo, tmp, return FALSE); + if (tmp != 0) { /* A(3,2)=0 */ + bad: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + + /* OK, valid transform that we can handle. */ + cinfo->color_transform = JCT_SUBTRACT_GREEN; + + INPUT_SYNC(cinfo); + return TRUE; +} + + /* * Routines for processing APPn and COM markers. * These are either saved in memory or discarded, per application request. @@ -606,12 +740,13 @@ examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); /* Check version. - * Major version must be 1, anything else signals an incompatible change. + * Major version must be 1 or 2, anything else signals an incompatible + * change. * (We used to treat this as an error, but now it's a nonfatal warning, * because some bozo at Hijaak couldn't read the spec.) * Minor version should be 0..2, but process anyway if newer. */ - if (cinfo->JFIF_major_version != 1) + if (cinfo->JFIF_major_version != 1 && cinfo->JFIF_major_version != 2) WARNMS2(cinfo, JWRN_JFIF_MAJOR, cinfo->JFIF_major_version, cinfo->JFIF_minor_version); /* Generate trace messages */ @@ -852,7 +987,7 @@ skip_variable (j_decompress_ptr cinfo) INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; - + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); INPUT_SYNC(cinfo); /* do before skip_input_data */ @@ -948,6 +1083,11 @@ first_marker (j_decompress_ptr cinfo) * * Returns same codes as are defined for jpeg_consume_input: * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * Note: This function may return a pseudo SOS marker (with zero + * component number) for treat by input controller's consume_input. + * consume_input itself should filter out (skip) the pseudo marker + * after processing for the caller. */ METHODDEF(int) @@ -977,41 +1117,37 @@ read_markers (j_decompress_ptr cinfo) break; case M_SOF0: /* Baseline */ + if (! get_sof(cinfo, TRUE, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + case M_SOF1: /* Extended sequential, Huffman */ - if (! get_sof(cinfo, JPROC_SEQUENTIAL, FALSE, DCTSIZE)) + if (! get_sof(cinfo, FALSE, FALSE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF2: /* Progressive, Huffman */ - if (! get_sof(cinfo, JPROC_PROGRESSIVE, FALSE, DCTSIZE)) - return JPEG_SUSPENDED; - break; - - case M_SOF3: /* Lossless, Huffman */ - if (! get_sof(cinfo, JPROC_LOSSLESS, FALSE, 1)) + if (! get_sof(cinfo, FALSE, TRUE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF9: /* Extended sequential, arithmetic */ - if (! get_sof(cinfo, JPROC_SEQUENTIAL, TRUE, DCTSIZE)) + if (! get_sof(cinfo, FALSE, FALSE, TRUE)) return JPEG_SUSPENDED; break; case M_SOF10: /* Progressive, arithmetic */ - if (! get_sof(cinfo, JPROC_PROGRESSIVE, TRUE, DCTSIZE)) - return JPEG_SUSPENDED; - break; - - case M_SOF11: /* Lossless, arithmetic */ - if (! get_sof(cinfo, JPROC_LOSSLESS, TRUE, 1)) + if (! get_sof(cinfo, FALSE, TRUE, TRUE)) return JPEG_SUSPENDED; break; /* Currently unsupported SOFn types */ + case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */ @@ -1049,6 +1185,11 @@ read_markers (j_decompress_ptr cinfo) return JPEG_SUSPENDED; break; + case M_JPG8: + if (! get_lse(cinfo)) + return JPEG_SUSPENDED; + break; + case M_APP0: case M_APP1: case M_APP2: @@ -1203,10 +1344,10 @@ jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) { int marker = cinfo->unread_marker; int action = 1; - + /* Always put up a warning. */ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); - + /* Outer loop handles repeated decision after scanning forward. */ for (;;) { if (marker < (int) M_SOF0) @@ -1278,7 +1419,7 @@ jinit_marker_reader (j_decompress_ptr cinfo) marker = (my_marker_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_marker_reader)); - cinfo->marker = (struct jpeg_marker_reader *) marker; + cinfo->marker = &marker->pub; /* Initialize public method pointers */ marker->pub.reset_marker_reader = reset_marker_reader; marker->pub.read_markers = read_markers; diff --git a/uppsrc/plugin/jpg/lib/jdmaster.c b/uppsrc/plugin/jpg/lib/jdmaster.c index e92c1c4ea..0ece558cb 100644 --- a/uppsrc/plugin/jpg/lib/jdmaster.c +++ b/uppsrc/plugin/jpg/lib/jdmaster.c @@ -1,7 +1,8 @@ /* * jdmaster.c * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -44,13 +45,26 @@ LOCAL(boolean) use_merged_upsample (j_decompress_ptr cinfo) { #ifdef UPSAMPLE_MERGING_SUPPORTED - /* Merging is the equivalent of plain box-filter upsampling */ - if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + /* Merging is the equivalent of plain box-filter upsampling. */ + /* The following condition is only needed if fancy shall select + * a different upsampling method. In our current implementation + * fancy only affects the DCT scaling, thus we can use fancy + * upsampling and merged upsample simultaneously, in particular + * with scaled DCT sizes larger than the default DCTSIZE. + */ +#if 0 + if (cinfo->do_fancy_upsampling) + return FALSE; +#endif + if (cinfo->CCIR601_sampling) return FALSE; /* jdmerge.c only supports YCC=>RGB color conversion */ - if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + if ((cinfo->jpeg_color_space != JCS_YCbCr && + cinfo->jpeg_color_space != JCS_BG_YCC) || + cinfo->num_components != 3 || cinfo->out_color_space != JCS_RGB || - cinfo->out_color_components != RGB_PIXELSIZE) + cinfo->out_color_components != RGB_PIXELSIZE || + cinfo->color_transform) return FALSE; /* and it only handles 2h1v or 2h2v sampling ratios */ if (cinfo->comp_info[0].h_samp_factor != 2 || @@ -60,11 +74,13 @@ use_merged_upsample (j_decompress_ptr cinfo) cinfo->comp_info[1].v_samp_factor != 1 || cinfo->comp_info[2].v_samp_factor != 1) return FALSE; - /* furthermore, it doesn't work if each component has been - processed differently */ - if (cinfo->comp_info[0].codec_data_unit != cinfo->min_codec_data_unit || - cinfo->comp_info[1].codec_data_unit != cinfo->min_codec_data_unit || - cinfo->comp_info[2].codec_data_unit != cinfo->min_codec_data_unit) + /* furthermore, it doesn't work if we've scaled the IDCTs differently */ + if (cinfo->comp_info[0].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[1].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[2].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[0].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || + cinfo->comp_info[1].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || + cinfo->comp_info[2].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size) return FALSE; /* ??? also need to test for upsample-time rescaling, when & if supported */ return TRUE; /* by golly, it'll work... */ @@ -83,13 +99,70 @@ use_merged_upsample (j_decompress_ptr cinfo) GLOBAL(void) jpeg_calc_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase */ +/* Do computations that are needed before master selection phase. + * This function is used for full decompression. + */ { +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; +#endif + /* Prevent application from calling me at wrong times */ if (cinfo->global_state != DSTATE_READY) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - (*cinfo->codec->calc_output_dimensions) (cinfo); + /* Compute core output image dimensions and DCT scaling choices. */ + jpeg_core_output_dimensions(cinfo); + +#ifdef IDCT_SCALING_SUPPORTED + + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code adapts subsampling ratios which are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = 1; + while (cinfo->min_DCT_h_scaled_size * ssize <= + (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; + ssize = 1; + while (cinfo->min_DCT_v_scaled_size * ssize <= + (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; + + /* We don't support IDCT ratios larger than 2. */ + if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; + else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) + compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + } + +#endif /* IDCT_SCALING_SUPPORTED */ /* Report number of components in selected colorspace. */ /* Probably this should be in the color conversion module... */ @@ -98,11 +171,11 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) cinfo->out_color_components = 1; break; case JCS_RGB: -#if RGB_PIXELSIZE != 3 + case JCS_BG_RGB: cinfo->out_color_components = RGB_PIXELSIZE; break; -#endif /* else share code with YCbCr */ case JCS_YCbCr: + case JCS_BG_YCC: cinfo->out_color_components = 3; break; case JCS_CMYK: @@ -138,30 +211,20 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) * These processes all use a common table prepared by the routine below. * * For most steps we can mathematically guarantee that the initial value - * of x is within MAXJSAMPLE+1 of the legal range, so a table running from - * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial - * limiting step (just after the IDCT), a wildly out-of-range value is - * possible if the input data is corrupt. To avoid any chance of indexing + * of x is within 2*(MAXJSAMPLE+1) of the legal range, so a table running + * from -2*(MAXJSAMPLE+1) to 3*MAXJSAMPLE+2 is sufficient. But for the + * initial limiting step (just after the IDCT), a wildly out-of-range value + * is possible if the input data is corrupt. To avoid any chance of indexing * off the end of memory and getting a bad-pointer trap, we perform the * post-IDCT limiting thus: - * x = range_limit[x & MASK]; + * x = (sample_range_limit - SUBSET)[(x + CENTER) & MASK]; * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit * samples. Under normal circumstances this is more than enough range and * a correct output will be generated; with bogus input data the mask will * cause wraparound, and we will safely generate a bogus-but-in-range output. * For the post-IDCT step, we want to convert the data from signed to unsigned * representation by adding CENTERJSAMPLE at the same time that we limit it. - * So the post-IDCT limiting table ends up looking like this: - * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, - * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0,1,...,CENTERJSAMPLE-1 - * Negative inputs select values from the upper half of the table after - * masking. - * - * We can save some space by overlapping the start of the post-IDCT table - * with the simpler range limiting table. The post-IDCT table begins at - * sample_range_limit + CENTERJSAMPLE. + * This is accomplished with SUBSET = CENTER - CENTERJSAMPLE. * * Note that the table is allocated in near data space on PCs; it's small * enough and used often enough to justify this. @@ -176,23 +239,17 @@ prepare_range_limit_table (j_decompress_ptr cinfo) table = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + 5 * (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* First segment of range limit table: limit[x] = 0 for x < 0 */ + MEMZERO(table, 2 * (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + table += 2 * (MAXJSAMPLE+1); /* allow negative subscripts of table */ cinfo->sample_range_limit = table; - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); - /* Main part of "simple" table: limit[x] = x */ + /* Main part of range limit table: limit[x] = x */ for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (JSAMPLE) i; - table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ - /* End of simple table, rest of first half of post-IDCT table */ - for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + /* End of range limit table: limit[x] = MAXJSAMPLE for x > MAXJSAMPLE */ + for (; i < 3 * (MAXJSAMPLE+1); i++) table[i] = MAXJSAMPLE; - /* Second half of post-IDCT table */ - MEMZERO(table + (2 * (MAXJSAMPLE+1)), - (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), - cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); } @@ -211,13 +268,23 @@ LOCAL(void) master_selection (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; + boolean use_c_buffer; long samplesperrow; JDIMENSION jd_samplesperrow; + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); + /* Sanity check on image dimensions */ + if (cinfo->output_height <= 0 || cinfo->output_width <= 0 || + cinfo->out_color_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + /* Width of an output scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; jd_samplesperrow = (JDIMENSION) samplesperrow; @@ -291,8 +358,19 @@ master_selection (j_decompress_ptr cinfo) } jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); } + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) + jinit_arith_decoder(cinfo); + else { + jinit_huff_decoder(cinfo); + } /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + if (! cinfo->raw_data_out) jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); @@ -311,7 +389,7 @@ master_selection (j_decompress_ptr cinfo) cinfo->inputctl->has_multiple_scans) { int nscans; /* Estimate number of scans to set pass_limit. */ - if (cinfo->process == JPROC_PROGRESSIVE) { + if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->num_components; } else { @@ -365,7 +443,8 @@ prepare_for_output_pass (j_decompress_ptr cinfo) ERREXIT(cinfo, JERR_MODE_CHANGE); } } - (*cinfo->codec->start_output_pass) (cinfo); + (*cinfo->idct->start_pass) (cinfo); + (*cinfo->coef->start_output_pass) (cinfo); if (! cinfo->raw_data_out) { if (! master->using_merged_upsample) (*cinfo->cconvert->start_pass) (cinfo); @@ -450,7 +529,7 @@ jinit_master_decompress (j_decompress_ptr cinfo) master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_decomp_master)); - cinfo->master = (struct jpeg_decomp_master *) master; + cinfo->master = &master->pub; master->pub.prepare_for_output_pass = prepare_for_output_pass; master->pub.finish_output_pass = finish_output_pass; diff --git a/uppsrc/plugin/jpg/lib/jdmerge.c b/uppsrc/plugin/jpg/lib/jdmerge.c index 9e3a595de..368fa703a 100644 --- a/uppsrc/plugin/jpg/lib/jdmerge.c +++ b/uppsrc/plugin/jpg/lib/jdmerge.c @@ -2,6 +2,7 @@ * jdmerge.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2013-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -23,7 +24,7 @@ * multiplications needed for color conversion. * * This file currently provides implementations for the following cases: - * YCbCr => RGB color conversion only. + * YCC => RGB color conversion only (YCbCr or BG_YCC). * Sampling ratios of 2h1v or 2h2v. * No scaling needed at upsample time. * Corner-aligned (non-CCIR601) sampling alignment. @@ -75,12 +76,13 @@ typedef my_upsampler * my_upsample_ptr; /* - * Initialize tables for YCC->RGB colorspace conversion. + * Initialize tables for YCbCr->RGB and BG_YCC->RGB colorspace conversion. * This is taken directly from jdcolor.c; see that file for more info. */ LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) +/* Normal case, sYCC */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int i; @@ -103,17 +105,57 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ + /* Cr=>R value is nearest int to 1.402 * x */ upsample->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ + RIGHT_SHIFT(FIX(1.402) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.772 * x */ upsample->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ + RIGHT_SHIFT(FIX(1.772) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.714136286 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.714136286)) * x; + /* Cb=>G value is scaled-up -0.344136286 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ - upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + upsample->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF; + } +} + + +LOCAL(void) +build_bg_ycc_rgb_table (j_decompress_ptr cinfo) +/* Wide gamut case, bg-sYCC */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + upsample->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 2.804 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(2.804) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 3.544 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(3.544) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -1.428272572 * x */ + upsample->Cr_g_tab[i] = (- FIX(1.428272572)) * x; + /* Cb=>G value is scaled-up -0.688272572 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF; } } @@ -250,32 +292,32 @@ h2v1_merged_upsample (j_decompress_ptr cinfo, /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; + cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; + cblue = Cbbtab[cb]; /* Fetch 2 Y values and emit 2 pixels */ y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr[RGB_BLUE] = range_limit[y + cblue]; outptr += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr[RGB_BLUE] = range_limit[y + cblue]; outptr += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; + cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; + cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr0); - outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr[RGB_BLUE] = range_limit[y + cblue]; } } @@ -314,46 +356,46 @@ h2v2_merged_upsample (j_decompress_ptr cinfo, /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; + cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; + cblue = Cbbtab[cb]; /* Fetch 4 Y values and emit 4 pixels */ y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; outptr1 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; outptr1 += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; + cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; + cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr00); - outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; y = GETJSAMPLE(*inptr01); - outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; } } @@ -374,7 +416,7 @@ jinit_merged_upsampler (j_decompress_ptr cinfo) upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; + cinfo->upsample = &upsample->pub; upsample->pub.start_pass = start_pass_merged_upsample; upsample->pub.need_context_rows = FALSE; @@ -394,7 +436,10 @@ jinit_merged_upsampler (j_decompress_ptr cinfo) upsample->spare_row = NULL; } - build_ycc_rgb_table(cinfo); + if (cinfo->jpeg_color_space == JCS_BG_YCC) + build_bg_ycc_rgb_table(cinfo); + else + build_ycc_rgb_table(cinfo); } #endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jdphuff.c b/uppsrc/plugin/jpg/lib/jdphuff.c deleted file mode 100644 index 3efde9f1e..000000000 --- a/uppsrc/plugin/jpg/lib/jdphuff.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * jdphuff.c - * - * Copyright (C) 1995-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines for progressive JPEG. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy subsystem */ -#include "jdhuff.h" /* Declarations shared with jd*huff.c */ - - -#ifdef D_PROGRESSIVE_SUPPORTED - -/* - * Private entropy decoder object for progressive Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).EOBRUN = (src).EOBRUN, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - huffd_common_fields; /* Fields shared with other entropy decoders */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ -} phuff_entropy_decoder; - -typedef phuff_entropy_decoder * phuff_entropy_ptr; - -/* Forward declarations */ -METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_phuff_decoder (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; - boolean is_DC_band, bad; - int ci, coefi, tbl; - int *coef_bit_ptr; - jpeg_component_info * compptr; - - is_DC_band = (cinfo->Ss == 0); - - /* Validate scan parameters */ - bad = FALSE; - if (is_DC_band) { - if (cinfo->Se != 0) - bad = TRUE; - } else { - /* need not check Ss/Se < 0 since they came from unsigned bytes */ - if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) - bad = TRUE; - /* AC scans may have only one component */ - if (cinfo->comps_in_scan != 1) - bad = TRUE; - } - if (cinfo->Ah != 0) { - /* Successive approximation refinement scan: must have Al = Ah-1. */ - if (cinfo->Al != cinfo->Ah-1) - bad = TRUE; - } - if (cinfo->Al > 13) /* need not check for < 0 */ - bad = TRUE; - /* Arguably the maximum Al value should be less than 13 for 8-bit precision, - * but the spec doesn't say so, and we try to be liberal about what we - * accept. Note: large Al values could result in out-of-range DC - * coefficients during early scans, leading to bizarre displays due to - * overflows in the IDCT math. But we won't crash. - */ - if (bad) - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - /* Update progression status, and verify that scan order is legal. - * Note that inter-scan inconsistencies are treated as warnings - * not fatal errors ... not clear if this is right way to behave. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - int cindex = cinfo->cur_comp_info[ci]->component_index; - coef_bit_ptr = & cinfo->coef_bits[cindex][0]; - if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); - for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; - } - } - - /* Select MCU decoding routine */ - if (cinfo->Ah == 0) { - if (is_DC_band) - lossyd->entropy_decode_mcu = decode_mcu_DC_first; - else - lossyd->entropy_decode_mcu = decode_mcu_AC_first; - } else { - if (is_DC_band) - lossyd->entropy_decode_mcu = decode_mcu_DC_refine; - else - lossyd->entropy_decode_mcu = decode_mcu_AC_refine; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Make sure requested tables are present, and compute derived tables. - * We may build same derived table more than once, but it's not expensive. - */ - if (is_DC_band) { - if (cinfo->Ah == 0) { /* DC refinement needs no table */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->derived_tbls[tbl]); - } - } else { - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->derived_tbls[tbl]); - /* remember the single active table */ - entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->insufficient_data = FALSE; - - /* Initialize private state variables */ - entropy->saved.EOBRUN = 0; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL(boolean) -process_restart (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; - int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Re-init EOB run count, too */ - entropy->saved.EOBRUN = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Huffman MCU decoding. - * Each of these routines decodes and returns one MCU's worth of - * Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. - * - * We return FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * spectral selection, since we'll just re-assign them on the next call. - * Successive approximation AC refinement has to be more careful, however.) - */ - -/* - * MCU decoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; - int Al = cinfo->Al; - register int s, r; - int blkn, ci; - JBLOCKROW block; - BITREAD_STATE_VARS; - savable_state state; - d_derived_tbl * tbl; - jpeg_component_info * compptr; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - tbl = entropy->derived_tbls[compptr->dc_tbl_no]; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, tbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - /* Convert DC difference to actual value, update last_dc_val */ - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ - (*block)[0] = (JCOEF) (s << Al); - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; - int Se = cinfo->Se; - int Al = cinfo->Al; - register int s, k, r; - unsigned int EOBRUN; - JBLOCKROW block; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->insufficient_data) { - - /* Load up working state. - * We can avoid loading/saving bitread state if in an EOB run. - */ - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - - if (EOBRUN > 0) /* if it's a band of zeroes... */ - EOBRUN--; /* ...process it now (we do nothing) */ - else { - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - for (k = cinfo->Ss; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, return FALSE, label2); - r = s >> 4; - s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Scale and output coefficient in natural (dezigzagged) order */ - (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); - } else { - if (r == 15) { /* ZRL */ - k += 15; /* skip 15 zeroes in band */ - } else { /* EOBr, run length is 2^r + appended bits */ - EOBRUN = 1 << r; - if (r) { /* EOBr, r > 0 */ - CHECK_BIT_BUFFER(br_state, r, return FALSE); - r = GET_BITS(r); - EOBRUN += r; - } - EOBRUN--; /* this band is processed at this moment */ - break; /* force end-of-band */ - } - } - } - - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - } - - /* Completed MCU, so update state */ - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - -METHODDEF(boolean) -decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int blkn; - JBLOCKROW block; - BITREAD_STATE_VARS; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* Not worth the cycles to check insufficient_data here, - * since we will not change the data anyway if we read zeroes. - */ - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { - block = MCU_data[blkn]; - - /* Encoded data is simply the next bit of the two's-complement DC value */ - CHECK_BIT_BUFFER(br_state, 1, return FALSE); - if (GET_BITS(1)) - (*block)[0] |= p1; - /* Note: since we use |=, repeating the assignment later is safe */ - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; - int Se = cinfo->Se; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ - register int s, k, r; - unsigned int EOBRUN; - JBLOCKROW block; - JCOEFPTR thiscoef; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - int num_newnz; - int newnz_pos[DCTSIZE2]; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, don't modify the MCU. - */ - if (! entropy->insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - /* If we are forced to suspend, we must undo the assignments to any newly - * nonzero coefficients in the block, because otherwise we'd get confused - * next time about which coefficients were already nonzero. - * But we need not undo addition of bits to already-nonzero coefficients; - * instead, we can test the current bit to see if we already did it. - */ - num_newnz = 0; - - /* initialize coefficient loop counter to start of band */ - k = cinfo->Ss; - - if (EOBRUN == 0) { - for (; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, goto undoit, label3); - r = s >> 4; - s &= 15; - if (s) { - if (s != 1) /* size of new coef should always be 1 */ - WARNMS(cinfo, JWRN_HUFF_BAD_CODE); - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) - s = p1; /* newly nonzero coef is positive */ - else - s = m1; /* newly nonzero coef is negative */ - } else { - if (r != 15) { - EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ - if (r) { - CHECK_BIT_BUFFER(br_state, r, goto undoit); - r = GET_BITS(r); - EOBRUN += r; - } - break; /* rest of block is handled by EOB logic */ - } - /* note s = 0 for processing ZRL */ - } - /* Advance over already-nonzero coefs and r still-zero coefs, - * appending correction bits to the nonzeroes. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - do { - thiscoef = *block + jpeg_natural_order[k]; - if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } else { - if (--r < 0) - break; /* reached target zero coefficient */ - } - k++; - } while (k <= Se); - if (s) { - int pos = jpeg_natural_order[k]; - /* Output newly nonzero coefficient */ - (*block)[pos] = (JCOEF) s; - /* Remember its position in case we have to suspend */ - newnz_pos[num_newnz++] = pos; - } - } - } - - if (EOBRUN > 0) { - /* Scan any remaining coefficient positions after the end-of-band - * (the last newly nonzero coefficient, if any). Append a correction - * bit to each already-nonzero coefficient. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - for (; k <= Se; k++) { - thiscoef = *block + jpeg_natural_order[k]; - if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } - } - /* Count one block completed in EOB run */ - EOBRUN--; - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; - -undoit: - /* Re-zero any output coefficients that we made newly nonzero */ - while (num_newnz > 0) - (*block)[newnz_pos[--num_newnz]] = 0; - - return FALSE; -} - - -/* - * Module initialization routine for progressive Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_phuff_decoder (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - phuff_entropy_ptr entropy; - int *coef_bit_ptr; - int ci, i; - - entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(phuff_entropy_decoder)); - lossyd->entropy_private = (void *) entropy; - lossyd->entropy_start_pass = start_pass_phuff_decoder; - - /* Mark derived tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - } - - /* Create progression status table */ - cinfo->coef_bits = (int (*)[DCTSIZE2]) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components*DCTSIZE2*SIZEOF(int)); - coef_bit_ptr = & cinfo->coef_bits[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; -} - -#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jdpred.c b/uppsrc/plugin/jpg/lib/jdpred.c deleted file mode 100644 index 3b7a51d9f..000000000 --- a/uppsrc/plugin/jpg/lib/jdpred.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * jdpred.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains sample undifferencing (reconstruction) for lossless JPEG. - * - * In order to avoid paying the performance penalty of having to check the - * predictor being used and the row being processed for each call of the - * undifferencer, and to promote optimization, we have separate undifferencing - * functions for each case. - * - * We are able to avoid duplicating source code by implementing the predictors - * and undifferencers as macros. Each of the undifferencing functions are - * simply wrappers around an UNDIFFERENCE macro with the appropriate PREDICTOR - * macro passed as an argument. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" /* Private declarations for lossless codec */ - - -#ifdef D_LOSSLESS_SUPPORTED - -/* Predictor for the first column of the first row: 2^(P-Pt-1) */ -#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) - -/* Predictor for the first column of the remaining rows: Rb */ -#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0]) - - -/* - * 1-Dimensional undifferencer routine. - * - * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR - * is used as the special case predictor for the first column, which must be - * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples - * use PREDICTOR1. - * - * The reconstructed sample is supposed to be calculated modulo 2^16, so we - * logically AND the result with 0xFFFF. -*/ - -#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \ - unsigned xindex; \ - int Ra; \ - \ - Ra = (diff_buf[0] + INITIAL_PREDICTOR) & 0xFFFF; \ - undiff_buf[0] = Ra; \ - \ - for (xindex = 1; xindex < width; xindex++) { \ - Ra = (diff_buf[xindex] + PREDICTOR1) & 0xFFFF; \ - undiff_buf[xindex] = Ra; \ - } - -/* - * 2-Dimensional undifferencer routine. - * - * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is - * used as the special case predictor for the first column. The remaining - * samples use PREDICTOR, which is a function of Ra, Rb, Rc. - * - * Because prev_row and output_buf may point to the same storage area (in an - * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc - * before writing the current reconstructed sample value into output_buf. - * - * The reconstructed sample is supposed to be calculated modulo 2^16, so we - * logically AND the result with 0xFFFF. - */ - -#define UNDIFFERENCE_2D(PREDICTOR) \ - unsigned xindex; \ - int Ra, Rb, Rc; \ - \ - Rb = GETJSAMPLE(prev_row[0]); \ - Ra = (diff_buf[0] + PREDICTOR2) & 0xFFFF; \ - undiff_buf[0] = Ra; \ - \ - for (xindex = 1; xindex < width; xindex++) { \ - Rc = Rb; \ - Rb = GETJSAMPLE(prev_row[xindex]); \ - Ra = (diff_buf[xindex] + PREDICTOR) & 0xFFFF; \ - undiff_buf[xindex] = Ra; \ - } \ - (void)Rc; - - -/* - * Undifferencers for the all rows but the first in a scan or restart interval. - * The first sample in the row is undifferenced using the vertical - * predictor (2). The rest of the samples are undifferenced using the - * predictor specified in the scan header. - */ - -METHODDEF(void) -jpeg_undifference1(j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width) -{ - UNDIFFERENCE_1D(INITIAL_PREDICTOR2); -} - -METHODDEF(void) -jpeg_undifference2(j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width) -{ - UNDIFFERENCE_2D(PREDICTOR2); -} - -METHODDEF(void) -jpeg_undifference3(j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width) -{ - UNDIFFERENCE_2D(PREDICTOR3); -} - -METHODDEF(void) -jpeg_undifference4(j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width) -{ - UNDIFFERENCE_2D(PREDICTOR4); -} - -METHODDEF(void) -jpeg_undifference5(j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width) -{ - UNDIFFERENCE_2D(PREDICTOR5); -} - -METHODDEF(void) -jpeg_undifference6(j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width) -{ - UNDIFFERENCE_2D(PREDICTOR6); -} - -METHODDEF(void) -jpeg_undifference7(j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width) -{ - UNDIFFERENCE_2D(PREDICTOR7); -} - - -/* - * Undifferencer for the first row in a scan or restart interval. The first - * sample in the row is undifferenced using the special predictor constant - * x=2^(P-Pt-1). The rest of the samples are undifferenced using the - * 1-D horizontal predictor (1). - */ - -METHODDEF(void) -jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - - UNDIFFERENCE_1D(INITIAL_PREDICTORx); - - /* - * Now that we have undifferenced the first row, we want to use the - * undifferencer which corresponds to the predictor specified in the - * scan header. - */ - switch (cinfo->Ss) { - case 1: - losslsd->predict_undifference[comp_index] = jpeg_undifference1; - break; - case 2: - losslsd->predict_undifference[comp_index] = jpeg_undifference2; - break; - case 3: - losslsd->predict_undifference[comp_index] = jpeg_undifference3; - break; - case 4: - losslsd->predict_undifference[comp_index] = jpeg_undifference4; - break; - case 5: - losslsd->predict_undifference[comp_index] = jpeg_undifference5; - break; - case 6: - losslsd->predict_undifference[comp_index] = jpeg_undifference6; - break; - case 7: - losslsd->predict_undifference[comp_index] = jpeg_undifference7; - break; - } -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF(void) -predict_start_pass (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - int ci; - - /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG. - * - * Ss is the predictor selection value (psv). Legal values for sequential - * lossless JPEG are: 1 <= psv <= 7. - * - * Se and Ah are not used and should be zero. - * - * Al specifies the point transform (Pt). Legal values are: 0 <= Pt <= 15. - */ - if (cinfo->Ss < 1 || cinfo->Ss > 7 || - cinfo->Se != 0 || cinfo->Ah != 0 || - cinfo->Al > 15) /* need not check for < 0 */ - ERREXIT4(cinfo, JERR_BAD_LOSSLESS, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - - /* Set undifference functions to first row function */ - for (ci = 0; ci < cinfo->num_components; ci++) - losslsd->predict_undifference[ci] = jpeg_undifference_first_row; -} - - -/* - * Module initialization routine for the undifferencer. - */ - -GLOBAL(void) -jinit_undifferencer (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - - losslsd->predict_start_pass = predict_start_pass; - losslsd->predict_process_restart = predict_start_pass; -} - -#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jdsample.c b/uppsrc/plugin/jpg/lib/jdsample.c index 1832a8884..83d6332c3 100644 --- a/uppsrc/plugin/jpg/lib/jdsample.c +++ b/uppsrc/plugin/jpg/lib/jdsample.c @@ -1,14 +1,15 @@ /* * jdsample.c * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains upsampling routines. * * Upsampling input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit) + * is defined to be (v_samp_factor * DCT_v_scaled_size / min_DCT_v_scaled_size) * sample rows of each component. Upsampling will normally produce * max_v_samp_factor pixel rows from each row group (but this could vary * if the upsampler is applying a scale factor of its own). @@ -118,7 +119,7 @@ sep_upsample (j_decompress_ptr cinfo, /* Not more than the distance to the end of the image. Need this test * in case the image height is not a multiple of max_v_samp_factor: */ - if (num_rows > upsample->rows_to_go) + if (num_rows > upsample->rows_to_go) num_rows = upsample->rows_to_go; /* And not more than what the client can accept: */ out_rows_avail -= *out_row_ctr; @@ -237,11 +238,11 @@ h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, register JSAMPROW inptr, outptr; register JSAMPLE invalue; JSAMPROW outend; - int inrow; + int outrow; - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; + for (outrow = 0; outrow < cinfo->max_v_samp_factor; outrow++) { + inptr = input_data[outrow]; + outptr = output_data[outrow]; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ @@ -285,112 +286,6 @@ h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, } -/* - * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. - * - * The upsampling algorithm is linear interpolation between pixel centers, - * also known as a "triangle filter". This is a good compromise between - * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 - * of the way between input pixel centers. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - -METHODDEF(void) -h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register int invalue; - register JDIMENSION colctr; - int inrow; - - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - /* Special case for first column */ - invalue = GETJSAMPLE(*inptr++); - *outptr++ = (JSAMPLE) invalue; - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ - invalue = GETJSAMPLE(*inptr++) * 3; - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); - } - - /* Special case for last column */ - invalue = GETJSAMPLE(*inptr); - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); - *outptr++ = (JSAMPLE) invalue; - } -} - - -/* - * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. - * Again a triangle filter; see comments for h2v1 case, above. - * - * It is OK for us to reference the adjacent input rows because we demanded - * context from the main buffer controller (see initialization code). - */ - -METHODDEF(void) -h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr0, inptr1, outptr; -#if BITS_IN_JSAMPLE == 8 - register int thiscolsum, lastcolsum, nextcolsum; -#else - register INT32 thiscolsum, lastcolsum, nextcolsum; -#endif - register JDIMENSION colctr; - int inrow, outrow, v; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - for (v = 0; v < 2; v++) { - /* inptr0 points to nearest input row, inptr1 points to next nearest */ - inptr0 = input_data[inrow]; - if (v == 0) /* next nearest is row above */ - inptr1 = input_data[inrow-1]; - else /* next nearest is row below */ - inptr1 = input_data[inrow+1]; - outptr = output_data[outrow++]; - - /* Special case for first column */ - thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ - /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - } - - /* Special case for last column */ - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); - } - inrow++; - } -} - - /* * Module initialization routine for upsampling. */ @@ -401,13 +296,12 @@ jinit_upsampler (j_decompress_ptr cinfo) my_upsample_ptr upsample; int ci; jpeg_component_info * compptr; - boolean need_buffer, do_fancy; int h_in_group, v_in_group, h_out_group, v_out_group; upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; + cinfo->upsample = &upsample->pub; upsample->pub.start_pass = start_pass_upsample; upsample->pub.upsample = sep_upsample; upsample->pub.need_context_rows = FALSE; /* until we find out differently */ @@ -415,11 +309,6 @@ jinit_upsampler (j_decompress_ptr cinfo) if (cinfo->CCIR601_sampling) /* this isn't supported */ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - /* jdmainct.c doesn't support context rows when min_codec_data_unit = 1, - * so don't ask for it. - */ - do_fancy = cinfo->do_fancy_upsampling && cinfo->min_codec_data_unit > 1; - /* Verify we can handle the sampling factors, select per-component methods, * and create storage as needed. */ @@ -428,37 +317,30 @@ jinit_upsampler (j_decompress_ptr cinfo) /* Compute size of an "input group" after IDCT scaling. This many samples * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. */ - h_in_group = (compptr->h_samp_factor * compptr->codec_data_unit) / - cinfo->min_codec_data_unit; - v_in_group = (compptr->v_samp_factor * compptr->codec_data_unit) / - cinfo->min_codec_data_unit; + h_in_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / + cinfo->min_DCT_h_scaled_size; + v_in_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; h_out_group = cinfo->max_h_samp_factor; v_out_group = cinfo->max_v_samp_factor; upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ - need_buffer = TRUE; if (! compptr->component_needed) { /* Don't bother to upsample an uninteresting component. */ upsample->methods[ci] = noop_upsample; - need_buffer = FALSE; - } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + continue; /* don't need to allocate buffer */ + } + if (h_in_group == h_out_group && v_in_group == v_out_group) { /* Fullsize components can be processed without any work. */ upsample->methods[ci] = fullsize_upsample; - need_buffer = FALSE; - } else if (h_in_group * 2 == h_out_group && - v_in_group == v_out_group) { - /* Special cases for 2h1v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) - upsample->methods[ci] = h2v1_fancy_upsample; - else - upsample->methods[ci] = h2v1_upsample; + continue; /* don't need to allocate buffer */ + } + if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { + /* Special case for 2h1v upsampling */ + upsample->methods[ci] = h2v1_upsample; } else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group) { - /* Special cases for 2h2v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) { - upsample->methods[ci] = h2v2_fancy_upsample; - upsample->pub.need_context_rows = TRUE; - } else - upsample->methods[ci] = h2v2_upsample; + /* Special case for 2h2v upsampling */ + upsample->methods[ci] = h2v2_upsample; } else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ @@ -467,12 +349,10 @@ jinit_upsampler (j_decompress_ptr cinfo) upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - if (need_buffer) { - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) cinfo->output_width, - (long) cinfo->max_h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); - } + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); } } diff --git a/uppsrc/plugin/jpg/lib/jdscale.c b/uppsrc/plugin/jpg/lib/jdscale.c deleted file mode 100644 index 86991947b..000000000 --- a/uppsrc/plugin/jpg/lib/jdscale.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * jdscale.c - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains sample scaling for lossless JPEG. This is a - * combination of upscaling the undifferenced sample by 2^Pt and downscaling - * the sample to fit into JSAMPLE. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossls.h" /* Private declarations for lossless codec */ - - -#ifdef D_LOSSLESS_SUPPORTED - -/* - * Private scaler object for lossless decoding. - */ - -typedef struct { - int scale_factor; -} scaler; - -typedef scaler * scaler_ptr; - - -/* - * Scalers for packing sample differences into JSAMPLEs. - */ - -METHODDEF(void) -simple_upscale(j_decompress_ptr cinfo, - JDIFFROW diff_buf, JSAMPROW output_buf, - JDIMENSION width) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private; - int scale_factor = scaler->scale_factor; - unsigned xindex; - - for (xindex = 0; xindex < width; xindex++) - output_buf[xindex] = (JSAMPLE) (diff_buf[xindex] << scale_factor); -} - -METHODDEF(void) -simple_downscale(j_decompress_ptr cinfo, - JDIFFROW diff_buf, JSAMPROW output_buf, - JDIMENSION width) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private; - int scale_factor = scaler->scale_factor; - unsigned xindex; - - for (xindex = 0; xindex < width; xindex++) - output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(diff_buf[xindex], scale_factor); -} - -METHODDEF(void) -noscale(j_decompress_ptr cinfo, - JDIFFROW diff_buf, JSAMPROW output_buf, - JDIMENSION width) -{ - unsigned xindex; - - for (xindex = 0; xindex < width; xindex++) - output_buf[xindex] = (JSAMPLE) diff_buf[xindex]; -} - - -METHODDEF(void) -scaler_start_pass (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private; - int downscale; - - /* - * Downscale by the difference in the input vs. output precision. If the - * output precision >= input precision, then do not downscale. - */ - downscale = BITS_IN_JSAMPLE < cinfo->data_precision ? - cinfo->data_precision - BITS_IN_JSAMPLE : 0; - - scaler->scale_factor = cinfo->Al - downscale; - - /* Set scaler functions based on scale_factor (positive = left shift) */ - if (scaler->scale_factor > 0) - losslsd->scaler_scale = simple_upscale; - else if (scaler->scale_factor < 0) { - scaler->scale_factor = -scaler->scale_factor; - losslsd->scaler_scale = simple_downscale; - } - else - losslsd->scaler_scale = noscale; -} - - -GLOBAL(void) -jinit_d_scaler (j_decompress_ptr cinfo) -{ - j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; - scaler_ptr scaler; - - scaler = (scaler_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(scaler)); - losslsd->scaler_private = (void *) scaler; - losslsd->scaler_start_pass = scaler_start_pass; -} - -#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jdshuff.c b/uppsrc/plugin/jpg/lib/jdshuff.c deleted file mode 100644 index f34ace949..000000000 --- a/uppsrc/plugin/jpg/lib/jdshuff.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * jdshuff.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines for sequential JPEG. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jlossy.h" /* Private declarations for lossy codec */ -#include "jdhuff.h" /* Declarations shared with jd*huff.c */ - - -/* - * Private entropy decoder object for Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - huffd_common_fields; /* Fields shared with other entropy decoders */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; - - /* Precalculated info set up by start_pass for use in decode_mcu: */ - - /* Pointers to derived tables to be used for each block within an MCU */ - d_derived_tbl * dc_cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; - d_derived_tbl * ac_cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; - /* Whether we care about the DC and AC coefficient values for each block */ - boolean dc_needed[D_MAX_DATA_UNITS_IN_MCU]; - boolean ac_needed[D_MAX_DATA_UNITS_IN_MCU]; -} shuff_entropy_decoder; - -typedef shuff_entropy_decoder * shuff_entropy_ptr; - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_huff_decoder (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; - int ci, blkn, dctbl, actbl; - jpeg_component_info * compptr; - - /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. - * This ought to be an error condition, but we make it a warning because - * there are some baseline files out there with all zeroes in these bytes. - */ - if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || - cinfo->Ah != 0 || cinfo->Al != 0) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Precalculate decoding info for each block in an MCU of this scan */ - for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - /* Precalculate which table to use for each block */ - entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; - entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; - /* Decide whether we really care about the coefficient values */ - if (compptr->component_needed) { - entropy->dc_needed[blkn] = TRUE; - /* we don't need the ACs if producing a 1/8th-size image */ - entropy->ac_needed[blkn] = (compptr->codec_data_unit > 1); - } else { - entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; - } - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->insufficient_data = FALSE; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL(boolean) -process_restart (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; - int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Decode and return one MCU's worth of Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. - * (Wholesale zeroing is usually a little faster than retail...) - * - * Returns FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * this module, since we'll just re-assign them on the next call.) - */ - -METHODDEF(boolean) -decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; - int blkn; - BITREAD_STATE_VARS; - savable_state state; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { - JBLOCKROW block = MCU_data[blkn]; - d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; - d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; - register int s, k, r; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - if (entropy->dc_needed[blkn]) { - /* Convert DC difference to actual value, update last_dc_val */ - int ci = cinfo->MCU_membership[blkn]; - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ - (*block)[0] = (JCOEF) s; - } - - if (entropy->ac_needed[blkn]) { - - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label2); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in jpeg_natural_order[] will save us - * if k >= DCTSIZE2, which could happen if the data is corrupted. - */ - (*block)[jpeg_natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - break; - k += 15; - } - } - - } else { - - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label3); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } - } - - } - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * Module initialization routine for Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_shuff_decoder (j_decompress_ptr cinfo) -{ - j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; - shuff_entropy_ptr entropy; - int i; - - entropy = (shuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(shuff_entropy_decoder)); - lossyd->entropy_private = (void *) entropy; - lossyd->entropy_start_pass = start_pass_huff_decoder; - lossyd->entropy_decode_mcu = decode_mcu; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; - } -} - -/* - * BEWARE OF KLUDGE: This subroutine is a hack for decoding illegal JPEG-in- - * TIFF encapsulations produced by Microsoft's Wang Imaging - * for Windows application with the public-domain TIFF Library. Based upon an - * examination of selected output files, this program apparently divides a JPEG - * bit-stream into consecutive horizontal TIFF "strips", such that the JPEG - * encoder's/decoder's DC coefficients for each image component are reset before - * each "strip". Moreover, a "strip" is not necessarily encoded in a multiple - * of 8 bits, so one must sometimes discard 1-7 bits at the end of each "strip" - * for alignment to the next input-Byte storage boundary. IJG JPEG Library - * decoder state is not normally exposed to client applications, so this sub- - * routine provides the TIFF Library with a "hook" to make these corrections. - * It should be called after "jpeg_start_decompress()" and before - * "jpeg_finish_decompress()", just before decoding each "strip" using - * "jpeg_read_raw_data()" or "jpeg_read_scanlines()". - * - * This kludge is not sanctioned or supported by the Independent JPEG Group, and - * future changes to the IJG JPEG Library might invalidate it. Do not send bug - * reports about this code to IJG developers. Instead, contact the author for - * advice: Scott B. Marovich , Hewlett-Packard Labs, 6/01. - */ -GLOBAL(void) -jpeg_reset_huff_decode (register j_decompress_ptr cinfo) -{ register shuff_entropy_ptr entropy = (shuff_entropy_ptr) - ((j_lossy_d_ptr)cinfo->codec)->entropy_private; - register int ci = 0; - - /* Discard encoded input bits, up to the next Byte boundary */ - entropy->bitstate.bits_left &= ~7; - /* Re-initialize DC predictions to 0 */ - do entropy->saved.last_dc_val[ci] = 0; while (++ci < cinfo->comps_in_scan); -} diff --git a/uppsrc/plugin/jpg/lib/jdtrans.c b/uppsrc/plugin/jpg/lib/jdtrans.c index 43f226068..a51d69de4 100644 --- a/uppsrc/plugin/jpg/lib/jdtrans.c +++ b/uppsrc/plugin/jpg/lib/jdtrans.c @@ -1,7 +1,8 @@ /* * jdtrans.c * - * Copyright (C) 1995-1998, Thomas G. Lane. + * Copyright (C) 1995-1997, Thomas G. Lane. + * Modified 2000-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -13,7 +14,6 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jlossy.h" /* Forward declarations */ @@ -45,14 +45,6 @@ LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); GLOBAL(jvirt_barray_ptr *) jpeg_read_coefficients (j_decompress_ptr cinfo) { -// j_lossy_d_ptr decomp; - - /* Can't read coefficients from lossless streams */ - if (cinfo->process == JPROC_LOSSLESS) { - ERREXIT(cinfo, JERR_CANT_TRANSCODE); - return NULL; - } - if (cinfo->global_state == DSTATE_READY) { /* First call: initialize active modules */ transdecode_master_selection(cinfo); @@ -89,7 +81,7 @@ jpeg_read_coefficients (j_decompress_ptr cinfo) */ if ((cinfo->global_state == DSTATE_STOPPING || cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { - return ((j_lossy_d_ptr) cinfo->codec)->coef_arrays; + return cinfo->coef->coef_arrays; } /* Oops, improper usage */ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); @@ -108,8 +100,18 @@ transdecode_master_selection (j_decompress_ptr cinfo) /* This is effectively a buffered-image operation. */ cinfo->buffered_image = TRUE; - /* Initialize decompression codec */ - jinit_d_codec(cinfo); + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(cinfo); + + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) + jinit_arith_decoder(cinfo); + else { + jinit_huff_decoder(cinfo); + } + + /* Always get a full-image coefficient buffer. */ + jinit_d_coef_controller(cinfo, TRUE); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); @@ -121,7 +123,7 @@ transdecode_master_selection (j_decompress_ptr cinfo) if (cinfo->progress != NULL) { int nscans; /* Estimate number of scans to set pass_limit. */ - if (cinfo->process == JPROC_PROGRESSIVE) { + if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->num_components; } else if (cinfo->inputctl->has_multiple_scans) { diff --git a/uppsrc/plugin/jpg/lib/jerror.c b/uppsrc/plugin/jpg/lib/jerror.c index c98aed76e..cfaf083a3 100644 --- a/uppsrc/plugin/jpg/lib/jerror.c +++ b/uppsrc/plugin/jpg/lib/jerror.c @@ -2,6 +2,7 @@ * jerror.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2012-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -18,16 +19,16 @@ * These routines are used by both the compression and decompression code. */ +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jversion.h" #include "jerror.h" -#ifdef USE_WINDOWS_MESSAGEBOX -#include -#endif - #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif @@ -66,7 +67,7 @@ const char * const jpeg_std_message_table[] = { * or jpeg_destroy) at some point. */ -METHODDEF(void) +METHODDEF(noreturn_t) error_exit (j_common_ptr cinfo) { /* Always display the message */ diff --git a/uppsrc/plugin/jpg/lib/jerror.h b/uppsrc/plugin/jpg/lib/jerror.h index 86d55e41b..b32da9a5a 100644 --- a/uppsrc/plugin/jpg/lib/jerror.h +++ b/uppsrc/plugin/jpg/lib/jerror.h @@ -1,7 +1,8 @@ /* * jerror.h * - * Copyright (C) 1994-1998, Thomas G. Lane. + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2012 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -39,25 +40,21 @@ typedef enum { JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ /* For maintenance convenience, list is alphabetical by message code name */ -JMESSAGE(JERR_ARITH_NOTIMPL, - "Sorry, there are legal restrictions on arithmetic coding") JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") -JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") -JMESSAGE(JERR_BAD_DIFF, "spatial difference out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") JMESSAGE(JERR_BAD_LIB_VERSION, "Wrong JPEG library version: library is %d, caller expects %d") -JMESSAGE(JERR_BAD_LOSSLESS, - "Invalid lossless parameters Ss=%d Se=%d Ah=%d Al=%d") -JMESSAGE(JERR_BAD_LOSSLESS_SCRIPT, - "Invalid lossless parameters at scan script entry %d") JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") @@ -65,7 +62,6 @@ JMESSAGE(JERR_BAD_PROGRESSION, "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") JMESSAGE(JERR_BAD_PROG_SCRIPT, "Invalid progressive parameters at scan script entry %d") -JMESSAGE(JERR_BAD_RESTART, "Invalid restart interval: %d, must be an integer multiple of the number of MCUs in an MCU_row (%d)") JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") @@ -74,8 +70,6 @@ JMESSAGE(JERR_BAD_STRUCT_SIZE, JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") -JMESSAGE(JERR_CANT_TRANSCODE, - "Cannot transcode to/from lossless JPEG datastreams") JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") @@ -101,10 +95,10 @@ JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") -JMESSAGE(JERR_NO_LOSSLESS_SCRIPT, "Lossless encoding was requested but no scan script was supplied") JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") @@ -112,11 +106,11 @@ JMESSAGE(JERR_QUANT_COMPONENTS, "Cannot quantize more than %d color components") JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_BEFORE, "Invalid JPEG file structure: %s before SOF") JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") -JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") @@ -174,13 +168,12 @@ JMESSAGE(JTRC_THUMB_PALETTE, "JFIF extension marker: palette thumbnail image, length %u") JMESSAGE(JTRC_THUMB_RGB, "JFIF extension marker: RGB thumbnail image, length %u") -JMESSAGE(JTRC_UNKNOWN_LOSSLESS_IDS, - "Unrecognized component IDs %d %d %d, assuming RGB") -JMESSAGE(JTRC_UNKNOWN_LOSSY_IDS, +JMESSAGE(JTRC_UNKNOWN_IDS, "Unrecognized component IDs %d %d %d, assuming YCbCr") JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") JMESSAGE(JWRN_BOGUS_PROGRESSION, "Inconsistent progression sequence for component %d coefficient %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, @@ -189,8 +182,6 @@ JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") -JMESSAGE(JWRN_MUST_DOWNSCALE, - "Must downscale data from %d bits to %d") JMESSAGE(JWRN_MUST_RESYNC, "Corrupt JPEG data: found marker 0x%02x instead of RST%d") JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") @@ -240,6 +231,15 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") (cinfo)->err->msg_parm.i[2] = (p3), \ (cinfo)->err->msg_parm.i[3] = (p4), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXITS(cinfo,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ diff --git a/uppsrc/plugin/jpg/lib/jfdctflt.c b/uppsrc/plugin/jpg/lib/jfdctflt.c index 102f7d5ad..0cc054074 100644 --- a/uppsrc/plugin/jpg/lib/jfdctflt.c +++ b/uppsrc/plugin/jpg/lib/jfdctflt.c @@ -2,6 +2,7 @@ * jfdctflt.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -53,29 +54,35 @@ /* * Perform the forward DCT on one block of samples. + * + * cK represents cos(K*pi/16). */ GLOBAL(void) -jpeg_fdct_float (FAST_FLOAT * data) +jpeg_fdct_float (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; FAST_FLOAT *dataptr; + JSAMPROW elemptr; int ctr; /* Pass 1: process rows. */ dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Load data into workspace */ + tmp0 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7])); + tmp7 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7])); + tmp1 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6])); + tmp6 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6])); + tmp2 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5])); + tmp5 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5])); + tmp3 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4])); + tmp4 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4])); /* Even part */ @@ -84,7 +91,8 @@ jpeg_fdct_float (FAST_FLOAT * data) tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - dataptr[0] = tmp10 + tmp11; /* phase 3 */ + /* Apply unsigned->signed conversion. */ + dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ diff --git a/uppsrc/plugin/jpg/lib/jfdctfst.c b/uppsrc/plugin/jpg/lib/jfdctfst.c index f26221def..173d0d6fc 100644 --- a/uppsrc/plugin/jpg/lib/jfdctfst.c +++ b/uppsrc/plugin/jpg/lib/jfdctfst.c @@ -2,6 +2,7 @@ * jfdctfst.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -108,30 +109,36 @@ /* * Perform the forward DCT on one block of samples. + * + * cK represents cos(K*pi/16). */ GLOBAL(void) -jpeg_fdct_ifast (DCTELEM * data) +jpeg_fdct_ifast (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; DCTELEM z1, z2, z3, z4, z5, z11, z13; DCTELEM *dataptr; + JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. */ dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Load data into workspace */ + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp7 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp6 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp5 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + tmp4 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); /* Even part */ @@ -140,7 +147,8 @@ jpeg_fdct_ifast (DCTELEM * data) tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - dataptr[0] = tmp10 + tmp11; /* phase 3 */ + /* Apply unsigned->signed conversion. */ + dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ diff --git a/uppsrc/plugin/jpg/lib/jfdctint.c b/uppsrc/plugin/jpg/lib/jfdctint.c index a9058494d..6700fdde2 100644 --- a/uppsrc/plugin/jpg/lib/jfdctint.c +++ b/uppsrc/plugin/jpg/lib/jfdctint.c @@ -2,6 +2,7 @@ * jfdctint.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modification developed 2003-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -21,6 +22,23 @@ * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * We also provide FDCT routines with various input sample block sizes for + * direct resolution reduction or enlargement and for direct resolving the + * common 2x1 and 1x2 subsampling cases without additional resampling: NxN + * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 output DCT block. + * + * For N<8 we fill the remaining block coefficients with zero. + * For N>8 we apply a partial N-point FDCT on the input samples, computing + * just the lower 8 frequency coefficients and discarding the rest. + * + * We must scale the output coefficients of the N-point FDCT appropriately + * to the standard 8-point FDCT level by 8/N per 1-D pass. This scaling + * is folded into the constant multipliers (pass 2) and/or final/initial + * shifting. + * + * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases + * since there would be too many additional constants to pre-calculate. */ #define JPEG_INTERNALS @@ -36,7 +54,7 @@ */ #if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ + Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif @@ -137,75 +155,3159 @@ */ GLOBAL(void) -jpeg_fdct_islow (DCTELEM * data) +jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { - INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; + INT32 z1; DCTELEM *dataptr; + JSAMPROW elemptr; int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * cK represents sqrt(2) * cos(K*pi/16). + */ + + dataptr = data; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "c1" should be "c6". + */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + dataptr[2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + tmp12 += z1; + tmp13 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * cK represents sqrt(2) * cos(K*pi/16). + */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + * rotator "c1" should be "c6". */ - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + /* Add fudge factor here for final descale. */ + tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1)); + tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + tmp13 = tmp1 - tmp2; - dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); - dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), - CONST_BITS-PASS1_BITS); - dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), - CONST_BITS-PASS1_BITS); + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + + dataptr[DCTSIZE*2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. + * i0..i3 in the paper are tmp0..tmp3 here. */ - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); - z3 += z5; - z4 += z5; + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + tmp12 += z1; + tmp13 += z1; - dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); - dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); - dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); - dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#ifdef DCT_SCALING_SUPPORTED + + +/* + * Perform the forward DCT on a 7x7 sample block. + */ + +GLOBAL(void) +jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * cK represents sqrt(2) * cos(K*pi/14). + */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]); + tmp3 = GETJSAMPLE(elemptr[3]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); + + z1 = tmp0 + tmp2; + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */ + dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/7)**2 = 64/49, which we fold + * into the constant multipliers: + * cK now represents sqrt(2) * cos(K*pi/14) * 64/49. + */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4]; + + z1 = tmp0 + tmp2; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ + CONST_BITS+PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x6 sample block. + */ + +GLOBAL(void) +jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * cK represents sqrt(2) * cos(K*pi/12). + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS)); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)**2 = 16/9, which we fold + * into the constant multipliers: + * cK now represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 5x5 sample block. + */ + +GLOBAL(void) +jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/10). + */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]); + tmp2 = GETJSAMPLE(elemptr[2]); + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << (PASS1_BITS+1)); + tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */ + dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS-1); + dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */ + + dataptr[1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ + CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/5)**2 = 64/25, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * cK now represents sqrt(2) * cos(K*pi/10) * 32/25. + */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2]; + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x4 sample block. + */ + +GLOBAL(void) +jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We must also scale the output by (8/4)**2 = 2**2, which we add here. + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+2)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+2)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-3); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-2); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-2); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 3x3 sample block. + */ + +GLOBAL(void) +jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We scale the results further by 2**2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/6). + */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]); + tmp1 = GETJSAMPLE(elemptr[1]); + + tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+2)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ + CONST_BITS-PASS1_BITS-2); + + /* Odd part */ + + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ + CONST_BITS-PASS1_BITS-2); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/3)**2 = 64/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * cK now represents sqrt(2) * cos(K*pi/6) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1]; + + tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 2x2 sample block. + */ + +GLOBAL(void) +jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3; + JSAMPROW elemptr; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + */ + + /* Row 0 */ + elemptr = sample_data[0] + start_col; + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]); + tmp1 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]); + + /* Row 1 */ + elemptr = sample_data[1] + start_col; + + tmp2 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]); + tmp3 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]); + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/2)**2 = 2**4. + */ + + /* Column 0 */ + /* Apply unsigned->signed conversion. */ + data[DCTSIZE*0] = (tmp0 + tmp2 - 4 * CENTERJSAMPLE) << 4; + data[DCTSIZE*1] = (tmp0 - tmp2) << 4; + + /* Column 1 */ + data[DCTSIZE*0+1] = (tmp1 + tmp3) << 4; + data[DCTSIZE*1+1] = (tmp1 - tmp3) << 4; +} + + +/* + * Perform the forward DCT on a 1x1 sample block. + */ + +GLOBAL(void) +jpeg_fdct_1x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + DCTELEM dcval; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + dcval = GETJSAMPLE(sample_data[0][start_col]); + + /* We leave the result scaled up by an overall factor of 8. */ + /* We must also scale the output by (8/1)**2 = 2**6. */ + /* Apply unsigned->signed conversion. */ + data[0] = (dcval - CENTERJSAMPLE) << 6; +} + + +/* + * Perform the forward DCT on a 9x9 sample block. + */ + +GLOBAL(void) +jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2; + DCTELEM workspace[8]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * we scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/18). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[8]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[7]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[6]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[5]); + tmp4 = GETJSAMPLE(elemptr[4]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[8]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[7]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[6]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[5]); + + z1 = tmp0 + tmp2 + tmp3; + z2 = tmp1 + tmp4; + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) ((z1 + z2 - 9 * CENTERJSAMPLE) << 1); + dataptr[6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z2 - z2, FIX(0.707106781)), /* c6 */ + CONST_BITS-1); + z1 = MULTIPLY(tmp0 - tmp2, FIX(1.328926049)); /* c2 */ + z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(0.707106781)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.083350441)) /* c4 */ + + z1 + z2, CONST_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.245575608)) /* c8 */ + + z1 - z2, CONST_BITS-1); + + /* Odd part */ + + dataptr[3] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.224744871)), /* c3 */ + CONST_BITS-1); + + tmp11 = MULTIPLY(tmp11, FIX(1.224744871)); /* c3 */ + tmp0 = MULTIPLY(tmp10 + tmp12, FIX(0.909038955)); /* c5 */ + tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.483689525)); /* c7 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS-1); + + tmp2 = MULTIPLY(tmp12 - tmp13, FIX(1.392728481)); /* c1 */ + + dataptr[5] = (DCTELEM) DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 9) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/9)**2 = 64/81, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/18) * 128/81. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*0]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*7]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*6]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*5]; + tmp4 = dataptr[DCTSIZE*4]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*0]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*7]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*6]; + tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*5]; + + z1 = tmp0 + tmp2 + tmp3; + z2 = tmp1 + tmp4; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + z2, FIX(1.580246914)), /* 128/81 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z2 - z2, FIX(1.117403309)), /* c6 */ + CONST_BITS+2); + z1 = MULTIPLY(tmp0 - tmp2, FIX(2.100031287)); /* c2 */ + z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(1.117403309)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.711961190)) /* c4 */ + + z1 + z2, CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.388070096)) /* c8 */ + + z1 - z2, CONST_BITS+2); + + /* Odd part */ + + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.935399303)), /* c3 */ + CONST_BITS+2); + + tmp11 = MULTIPLY(tmp11, FIX(1.935399303)); /* c3 */ + tmp0 = MULTIPLY(tmp10 + tmp12, FIX(1.436506004)); /* c5 */ + tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.764348879)); /* c7 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS+2); + + tmp2 = MULTIPLY(tmp12 - tmp13, FIX(2.200854883)); /* c1 */ + + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 10x10 sample block. + */ + +GLOBAL(void) +jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM workspace[8*2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * we scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/20). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]); + tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]); + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << 1); + tmp12 += tmp12; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ + CONST_BITS-1); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ + CONST_BITS-1); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ + CONST_BITS-1); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << 1); + tmp2 <<= CONST_BITS; + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ + CONST_BITS-1); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ + (tmp11 << (CONST_BITS - 1)) - tmp2; + dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 10) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/10)**2 = 16/25, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/20) * 32/25. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0]; + tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ + CONST_BITS+2); + tmp12 += tmp12; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ + CONST_BITS+2); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ + CONST_BITS+2); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+2); + tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ + CONST_BITS+2); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ + MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on an 11x11 sample block. + */ + +GLOBAL(void) +jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 z1, z2, z3; + DCTELEM workspace[8*3]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * we scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/22). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[10]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[9]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[8]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[7]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[6]); + tmp5 = GETJSAMPLE(elemptr[5]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[10]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[9]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[8]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[7]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 - 11 * CENTERJSAMPLE) << 1); + tmp5 += tmp5; + tmp0 -= tmp5; + tmp1 -= tmp5; + tmp2 -= tmp5; + tmp3 -= tmp5; + tmp4 -= tmp5; + z1 = MULTIPLY(tmp0 + tmp3, FIX(1.356927976)) + /* c2 */ + MULTIPLY(tmp2 + tmp4, FIX(0.201263574)); /* c10 */ + z2 = MULTIPLY(tmp1 - tmp3, FIX(0.926112931)); /* c6 */ + z3 = MULTIPLY(tmp0 - tmp1, FIX(1.189712156)); /* c4 */ + dataptr[2] = (DCTELEM) + DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.018300590)) /* c2+c8-c6 */ + - MULTIPLY(tmp4, FIX(1.390975730)), /* c4+c10 */ + CONST_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.062335650)) /* c4-c6-c10 */ + - MULTIPLY(tmp2, FIX(1.356927976)) /* c2 */ + + MULTIPLY(tmp4, FIX(0.587485545)), /* c8 */ + CONST_BITS-1); + dataptr[6] = (DCTELEM) + DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.620527200)) /* c2+c4-c6 */ + - MULTIPLY(tmp2, FIX(0.788749120)), /* c8+c10 */ + CONST_BITS-1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.286413905)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.068791298)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.764581576)); /* c7 */ + tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.719967871)) /* c7+c5+c3-c1 */ + + MULTIPLY(tmp14, FIX(0.398430003)); /* c9 */ + tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.764581576)); /* -c7 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.399818907)); /* -c1 */ + tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.276416582)) /* c9+c7+c1-c3 */ + - MULTIPLY(tmp14, FIX(1.068791298)); /* c5 */ + tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.398430003)); /* c9 */ + tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(1.989053629)) /* c9+c5+c3-c7 */ + + MULTIPLY(tmp14, FIX(1.399818907)); /* c1 */ + tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.305598626)) /* c1+c5-c9-c7 */ + - MULTIPLY(tmp14, FIX(1.286413905)); /* c3 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-1); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-1); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 11) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/11)**2 = 64/121, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/22) * 128/121. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*1]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*0]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*7]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*6]; + tmp5 = dataptr[DCTSIZE*5]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*2]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*1]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*0]; + tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*7]; + tmp14 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5, + FIX(1.057851240)), /* 128/121 */ + CONST_BITS+2); + tmp5 += tmp5; + tmp0 -= tmp5; + tmp1 -= tmp5; + tmp2 -= tmp5; + tmp3 -= tmp5; + tmp4 -= tmp5; + z1 = MULTIPLY(tmp0 + tmp3, FIX(1.435427942)) + /* c2 */ + MULTIPLY(tmp2 + tmp4, FIX(0.212906922)); /* c10 */ + z2 = MULTIPLY(tmp1 - tmp3, FIX(0.979689713)); /* c6 */ + z3 = MULTIPLY(tmp0 - tmp1, FIX(1.258538479)); /* c4 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.077210542)) /* c2+c8-c6 */ + - MULTIPLY(tmp4, FIX(1.471445400)), /* c4+c10 */ + CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.065941844)) /* c4-c6-c10 */ + - MULTIPLY(tmp2, FIX(1.435427942)) /* c2 */ + + MULTIPLY(tmp4, FIX(0.621472312)), /* c8 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.714276708)) /* c2+c4-c6 */ + - MULTIPLY(tmp2, FIX(0.834379234)), /* c8+c10 */ + CONST_BITS+2); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.360834544)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.130622199)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.808813568)); /* c7 */ + tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.819470145)) /* c7+c5+c3-c1 */ + + MULTIPLY(tmp14, FIX(0.421479672)); /* c9 */ + tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.808813568)); /* -c7 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.480800167)); /* -c1 */ + tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.350258864)) /* c9+c7+c1-c3 */ + - MULTIPLY(tmp14, FIX(1.130622199)); /* c5 */ + tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.421479672)); /* c9 */ + tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(2.104122847)) /* c9+c5+c3-c7 */ + + MULTIPLY(tmp14, FIX(1.480800167)); /* c1 */ + tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.381129125)) /* c1+c5-c9-c7 */ + - MULTIPLY(tmp14, FIX(1.360834544)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 12x12 sample block. + */ + +GLOBAL(void) +jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM workspace[8*4]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * cK represents sqrt(2) * cos(K*pi/24). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]); + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) (tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE); + dataptr[6] = (DCTELEM) (tmp13 - tmp14 - tmp15); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ + CONST_BITS); + dataptr[2] = (DCTELEM) + DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ + CONST_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 12) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/12)**2 = 4/9, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/24) * 8/9. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6]; + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ + CONST_BITS+1); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ + MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ + CONST_BITS+1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 13x13 sample block. + */ + +GLOBAL(void) +jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 z1, z2; + DCTELEM workspace[8*5]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * cK represents sqrt(2) * cos(K*pi/26). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[12]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[11]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[10]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[9]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[8]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[7]); + tmp6 = GETJSAMPLE(elemptr[6]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[12]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[11]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[10]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[9]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[8]); + tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + (tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6 - 13 * CENTERJSAMPLE); + tmp6 += tmp6; + tmp0 -= tmp6; + tmp1 -= tmp6; + tmp2 -= tmp6; + tmp3 -= tmp6; + tmp4 -= tmp6; + tmp5 -= tmp6; + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.373119086)) + /* c2 */ + MULTIPLY(tmp1, FIX(1.058554052)) + /* c6 */ + MULTIPLY(tmp2, FIX(0.501487041)) - /* c10 */ + MULTIPLY(tmp3, FIX(0.170464608)) - /* c12 */ + MULTIPLY(tmp4, FIX(0.803364869)) - /* c8 */ + MULTIPLY(tmp5, FIX(1.252223920)), /* c4 */ + CONST_BITS); + z1 = MULTIPLY(tmp0 - tmp2, FIX(1.155388986)) - /* (c4+c6)/2 */ + MULTIPLY(tmp3 - tmp4, FIX(0.435816023)) - /* (c2-c10)/2 */ + MULTIPLY(tmp1 - tmp5, FIX(0.316450131)); /* (c8-c12)/2 */ + z2 = MULTIPLY(tmp0 + tmp2, FIX(0.096834934)) - /* (c4-c6)/2 */ + MULTIPLY(tmp3 + tmp4, FIX(0.937303064)) + /* (c2+c10)/2 */ + MULTIPLY(tmp1 + tmp5, FIX(0.486914739)); /* (c8+c12)/2 */ + + dataptr[4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.322312651)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.163874945)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.937797057)) + /* c7 */ + MULTIPLY(tmp14 + tmp15, FIX(0.338443458)); /* c11 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(tmp10, FIX(2.020082300)) + /* c3+c5+c7-c1 */ + MULTIPLY(tmp14, FIX(0.318774355)); /* c9-c11 */ + tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.937797057)) - /* c7 */ + MULTIPLY(tmp11 + tmp12, FIX(0.338443458)); /* c11 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.163874945)); /* -c5 */ + tmp1 += tmp4 + tmp5 + + MULTIPLY(tmp11, FIX(0.837223564)) - /* c5+c9+c11-c3 */ + MULTIPLY(tmp14, FIX(2.341699410)); /* c1+c7 */ + tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.657217813)); /* -c9 */ + tmp2 += tmp4 + tmp6 - + MULTIPLY(tmp12, FIX(1.572116027)) + /* c1+c5-c9-c11 */ + MULTIPLY(tmp15, FIX(2.260109708)); /* c3+c7 */ + tmp3 += tmp5 + tmp6 + + MULTIPLY(tmp13, FIX(2.205608352)) - /* c3+c5+c9-c7 */ + MULTIPLY(tmp15, FIX(1.742345811)); /* c1+c11 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 13) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/13)**2 = 64/169, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/26) * 128/169. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*2]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*1]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*0]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*7]; + tmp6 = dataptr[DCTSIZE*6]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*4]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*3]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*2]; + tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*1]; + tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*0]; + tmp15 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6, + FIX(0.757396450)), /* 128/169 */ + CONST_BITS+1); + tmp6 += tmp6; + tmp0 -= tmp6; + tmp1 -= tmp6; + tmp2 -= tmp6; + tmp3 -= tmp6; + tmp4 -= tmp6; + tmp5 -= tmp6; + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.039995521)) + /* c2 */ + MULTIPLY(tmp1, FIX(0.801745081)) + /* c6 */ + MULTIPLY(tmp2, FIX(0.379824504)) - /* c10 */ + MULTIPLY(tmp3, FIX(0.129109289)) - /* c12 */ + MULTIPLY(tmp4, FIX(0.608465700)) - /* c8 */ + MULTIPLY(tmp5, FIX(0.948429952)), /* c4 */ + CONST_BITS+1); + z1 = MULTIPLY(tmp0 - tmp2, FIX(0.875087516)) - /* (c4+c6)/2 */ + MULTIPLY(tmp3 - tmp4, FIX(0.330085509)) - /* (c2-c10)/2 */ + MULTIPLY(tmp1 - tmp5, FIX(0.239678205)); /* (c8-c12)/2 */ + z2 = MULTIPLY(tmp0 + tmp2, FIX(0.073342435)) - /* (c4-c6)/2 */ + MULTIPLY(tmp3 + tmp4, FIX(0.709910013)) + /* (c2+c10)/2 */ + MULTIPLY(tmp1 + tmp5, FIX(0.368787494)); /* (c8+c12)/2 */ + + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS+1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.001514908)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(0.881514751)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.710284161)) + /* c7 */ + MULTIPLY(tmp14 + tmp15, FIX(0.256335874)); /* c11 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(tmp10, FIX(1.530003162)) + /* c3+c5+c7-c1 */ + MULTIPLY(tmp14, FIX(0.241438564)); /* c9-c11 */ + tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.710284161)) - /* c7 */ + MULTIPLY(tmp11 + tmp12, FIX(0.256335874)); /* c11 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(0.881514751)); /* -c5 */ + tmp1 += tmp4 + tmp5 + + MULTIPLY(tmp11, FIX(0.634110155)) - /* c5+c9+c11-c3 */ + MULTIPLY(tmp14, FIX(1.773594819)); /* c1+c7 */ + tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.497774438)); /* -c9 */ + tmp2 += tmp4 + tmp6 - + MULTIPLY(tmp12, FIX(1.190715098)) + /* c1+c5-c9-c11 */ + MULTIPLY(tmp15, FIX(1.711799069)); /* c3+c7 */ + tmp3 += tmp5 + tmp6 + + MULTIPLY(tmp13, FIX(1.670519935)) - /* c3+c5+c9-c7 */ + MULTIPLY(tmp15, FIX(1.319646532)); /* c1+c11 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 14x14 sample block. + */ + +GLOBAL(void) +jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + DCTELEM workspace[8*6]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * cK represents sqrt(2) * cos(K*pi/28). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]); + tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]); + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + (tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE); + tmp13 += tmp13; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ + CONST_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ + CONST_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ + CONST_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[7] = (DCTELEM) (tmp0 - tmp10 + tmp3 - tmp11 - tmp6); + tmp3 <<= CONST_BITS; + tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ + dataptr[5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ + CONST_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ + dataptr[3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ + CONST_BITS); + dataptr[1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - + MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ + CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 14) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/14)**2 = 16/49, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/28) * 32/49. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3]; + tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+1); + tmp13 += tmp13; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ + CONST_BITS+1); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ + CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ + CONST_BITS+1); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+1); + tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ + tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ + CONST_BITS+1); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ + CONST_BITS+1); + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ + - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ + CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 15x15 sample block. + */ + +GLOBAL(void) +jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM workspace[8*7]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * cK represents sqrt(2) * cos(K*pi/30). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[14]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[13]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[12]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[11]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[10]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[9]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[8]); + tmp7 = GETJSAMPLE(elemptr[7]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[14]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[13]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[12]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[11]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[10]); + tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[9]); + tmp16 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[8]); + + z1 = tmp0 + tmp4 + tmp5; + z2 = tmp1 + tmp3 + tmp6; + z3 = tmp2 + tmp7; + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) (z1 + z2 + z3 - 15 * CENTERJSAMPLE); + z3 += z3; + dataptr[6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z3, FIX(1.144122806)) - /* c6 */ + MULTIPLY(z2 - z3, FIX(0.437016024)), /* c12 */ + CONST_BITS); + tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; + z1 = MULTIPLY(tmp3 - tmp2, FIX(1.531135173)) - /* c2+c14 */ + MULTIPLY(tmp6 - tmp2, FIX(2.238241955)); /* c4+c8 */ + z2 = MULTIPLY(tmp5 - tmp2, FIX(0.798468008)) - /* c8-c14 */ + MULTIPLY(tmp0 - tmp2, FIX(0.091361227)); /* c2-c4 */ + z3 = MULTIPLY(tmp0 - tmp3, FIX(1.383309603)) + /* c2 */ + MULTIPLY(tmp6 - tmp5, FIX(0.946293579)) + /* c8 */ + MULTIPLY(tmp1 - tmp4, FIX(0.790569415)); /* (c6+c12)/2 */ + + dataptr[2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS); + dataptr[4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS); + + /* Odd part */ + + tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, + FIX(1.224744871)); /* c5 */ + tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.344997024)) + /* c3 */ + MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.831253876)); /* c9 */ + tmp12 = MULTIPLY(tmp12, FIX(1.224744871)); /* c5 */ + tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.406466353)) + /* c1 */ + MULTIPLY(tmp11 + tmp14, FIX(1.344997024)) + /* c3 */ + MULTIPLY(tmp13 + tmp15, FIX(0.575212477)); /* c11 */ + tmp0 = MULTIPLY(tmp13, FIX(0.475753014)) - /* c7-c11 */ + MULTIPLY(tmp14, FIX(0.513743148)) + /* c3-c9 */ + MULTIPLY(tmp16, FIX(1.700497885)) + tmp4 + tmp12; /* c1+c13 */ + tmp3 = MULTIPLY(tmp10, - FIX(0.355500862)) - /* -(c1-c7) */ + MULTIPLY(tmp11, FIX(2.176250899)) - /* c3+c9 */ + MULTIPLY(tmp15, FIX(0.869244010)) + tmp4 - tmp12; /* c11+c13 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 15) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/15)**2 = 64/225, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/30) * 256/225. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*3]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*2]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*1]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*0]; + tmp7 = dataptr[DCTSIZE*7]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*4]; + tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*3]; + tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*2]; + tmp15 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*1]; + tmp16 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*0]; + + z1 = tmp0 + tmp4 + tmp5; + z2 = tmp1 + tmp3 + tmp6; + z3 = tmp2 + tmp7; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + z2 + z3, FIX(1.137777778)), /* 256/225 */ + CONST_BITS+2); + z3 += z3; + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z3, FIX(1.301757503)) - /* c6 */ + MULTIPLY(z2 - z3, FIX(0.497227121)), /* c12 */ + CONST_BITS+2); + tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; + z1 = MULTIPLY(tmp3 - tmp2, FIX(1.742091575)) - /* c2+c14 */ + MULTIPLY(tmp6 - tmp2, FIX(2.546621957)); /* c4+c8 */ + z2 = MULTIPLY(tmp5 - tmp2, FIX(0.908479156)) - /* c8-c14 */ + MULTIPLY(tmp0 - tmp2, FIX(0.103948774)); /* c2-c4 */ + z3 = MULTIPLY(tmp0 - tmp3, FIX(1.573898926)) + /* c2 */ + MULTIPLY(tmp6 - tmp5, FIX(1.076671805)) + /* c8 */ + MULTIPLY(tmp1 - tmp4, FIX(0.899492312)); /* (c6+c12)/2 */ + + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS+2); + + /* Odd part */ + + tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, + FIX(1.393487498)); /* c5 */ + tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.530307725)) + /* c3 */ + MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.945782187)); /* c9 */ + tmp12 = MULTIPLY(tmp12, FIX(1.393487498)); /* c5 */ + tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.600246161)) + /* c1 */ + MULTIPLY(tmp11 + tmp14, FIX(1.530307725)) + /* c3 */ + MULTIPLY(tmp13 + tmp15, FIX(0.654463974)); /* c11 */ + tmp0 = MULTIPLY(tmp13, FIX(0.541301207)) - /* c7-c11 */ + MULTIPLY(tmp14, FIX(0.584525538)) + /* c3-c9 */ + MULTIPLY(tmp16, FIX(1.934788705)) + tmp4 + tmp12; /* c1+c13 */ + tmp3 = MULTIPLY(tmp10, - FIX(0.404480980)) - /* -(c1-c7) */ + MULTIPLY(tmp11, FIX(2.476089912)) - /* c3+c9 */ + MULTIPLY(tmp15, FIX(0.989006518)) + tmp4 - tmp12; /* c11+c13 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 16x16 sample block. + */ + +GLOBAL(void) +jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + DCTELEM workspace[DCTSIZE2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * cK represents sqrt(2) * cos(K*pi/32). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]); + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == DCTSIZE * 2) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/16)**2 = 1/2**2. + * cK represents sqrt(2) * cos(K*pi/32). + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0]; + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS+PASS1_BITS+2); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+10 */ + CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS+PASS1_BITS+2); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 16x8 sample block. + * + * 16-point FDCT in pass 1 (rows), 8-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + + dataptr = data; + ctr = 0; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]); + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by 8/16 = 1/2. + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "c1" should be "c6". + */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+1); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS+1); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + tmp12 += z1; + tmp13 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 14x7 sample block. + * + * 14-point FDCT in pass 1 (rows), 7-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero bottom row of output coefficient block. */ + MEMZERO(&data[DCTSIZE*7], SIZEOF(DCTELEM) * DCTSIZE); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28). + */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]); + tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]); + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE) << PASS1_BITS); + tmp13 += tmp13; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[7] = (DCTELEM) ((tmp0 - tmp10 + tmp3 - tmp11 - tmp6) << PASS1_BITS); + tmp3 <<= CONST_BITS; + tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ + dataptr[5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ + CONST_BITS-PASS1_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ + dataptr[3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ + CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - + MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ + CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/14)*(8/7) = 32/49, which we + * partially fold into the constant multipliers and final shifting: + * 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14) * 64/49. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4]; + + z1 = tmp0 + tmp2; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ + CONST_BITS+PASS1_BITS+1); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS+1); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 12x6 sample block. + * + * 12-point FDCT in pass 1 (rows), 6-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 2 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*6], SIZEOF(DCTELEM) * DCTSIZE * 2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24). + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]); + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[6] = (DCTELEM) ((tmp13 - tmp14 - tmp15) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ + CONST_BITS-PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/12)*(8/6) = 8/9, which we + * partially fold into the constant multipliers and final shifting: + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 10x5 sample block. + * + * 10-point FDCT in pass 1 (rows), 5-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 3 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*5], SIZEOF(DCTELEM) * DCTSIZE * 3); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20). + */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]); + tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]); + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << PASS1_BITS); + tmp12 += tmp12; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ + CONST_BITS-PASS1_BITS); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << PASS1_BITS); + tmp2 <<= CONST_BITS; + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ + CONST_BITS-PASS1_BITS); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ + (tmp11 << (CONST_BITS - 1)) - tmp2; + dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/10)*(8/5) = 32/25, which we + * fold into the constant multipliers: + * 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10) * 32/25. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2]; + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on an 8x4 sample block. + * + * 8-point FDCT in pass 1 (rows), 4-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 4 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*4], SIZEOF(DCTELEM) * DCTSIZE * 4); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We must also scale the output by 8/4 = 2, which we add here. + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "c1" should be "c6". + */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << (PASS1_BITS+1)); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-2); + + dataptr[2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-1); + dataptr[6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-1); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-2); + + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + tmp12 += z1; + tmp13 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS-PASS1_BITS-1); + dataptr[5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS-1); + dataptr[7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x3 sample block. + * + * 6-point FDCT in pass 1 (rows), 3-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS-1); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << (PASS1_BITS+1))); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << (PASS1_BITS+1)); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << (PASS1_BITS+1))); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1]; + + tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x2 sample block. + * + * 4-point FDCT in pass 1 (rows), 2-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We must also scale the output by (8/4)*(8/2) = 2**3, which we add here. + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ + + dataptr = data; + for (ctr = 0; ctr < 2; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+3)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+3)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-4); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-3); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-3); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -216,68 +3318,1092 @@ jpeg_fdct_islow (DCTELEM * data) */ dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part */ - /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". - */ + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1]; - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); - dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); - dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); + /* Odd part */ - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), - CONST_BITS+PASS1_BITS); - - /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. - */ - - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, - CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); dataptr++; /* advance pointer to next column */ } } + +/* + * Perform the forward DCT on a 2x1 sample block. + * + * 2-point FDCT in pass 1 (rows), 1-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_2x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + DCTELEM tmp0, tmp1; + JSAMPROW elemptr; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + elemptr = sample_data[0] + start_col; + + tmp0 = GETJSAMPLE(elemptr[0]); + tmp1 = GETJSAMPLE(elemptr[1]); + + /* We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/2)*(8/1) = 2**5. + */ + + /* Even part */ + + /* Apply unsigned->signed conversion. */ + data[0] = (tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5; + + /* Odd part */ + + data[1] = (tmp0 - tmp1) << 5; +} + + +/* + * Perform the forward DCT on an 8x16 sample block. + * + * 8-point FDCT in pass 1 (rows), 16-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + INT32 z1; + DCTELEM workspace[DCTSIZE2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "c1" should be "c6". + */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + tmp12 += z1; + tmp13 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == DCTSIZE * 2) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by 8/16 = 1/2. + * 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0]; + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS+PASS1_BITS+1); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 7x14 sample block. + * + * 7-point FDCT in pass 1 (rows), 14-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM workspace[8*6]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]); + tmp3 = GETJSAMPLE(elemptr[3]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); + + z1 = tmp0 + tmp2; + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */ + dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 14) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/7)*(8/14) = 32/49, which we + * fold into the constant multipliers: + * 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28) * 32/49. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3]; + tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+PASS1_BITS); + tmp13 += tmp13; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ + CONST_BITS+PASS1_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+PASS1_BITS); + tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ + tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ + CONST_BITS+PASS1_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ + - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x12 sample block. + * + * 6-point FDCT in pass 1 (rows), 12-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM workspace[8*4]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS)); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 12) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/12) = 8/9, which we + * fold into the constant multipliers: + * 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24) * 8/9. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6]; + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ + MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 5x10 sample block. + * + * 5-point FDCT in pass 1 (rows), 10-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM workspace[8*2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10). + */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]); + tmp2 = GETJSAMPLE(elemptr[2]); + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */ + dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */ + + dataptr[1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ + CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ + CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 10) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/5)*(8/10) = 32/25, which we + * fold into the constant multipliers: + * 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20) * 32/25. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0]; + tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp12 += tmp12; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ + CONST_BITS+PASS1_BITS); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ + CONST_BITS+PASS1_BITS); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ + MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x8 sample block. + * + * 4-point FDCT in pass 1 (rows), 8-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We must also scale the output by 8/4 = 2, which we add here. + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ + + dataptr = data; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+1)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-2); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "c1" should be "c6". + */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + /* Add fudge factor here for final descale. */ + tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1)); + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + + dataptr[DCTSIZE*2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + tmp12 += z1; + tmp13 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 3x6 sample block. + * + * 3-point FDCT in pass 1 (rows), 6-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6). + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]); + tmp1 = GETJSAMPLE(elemptr[1]); + + tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ + CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 2x4 sample block. + * + * 2-point FDCT in pass 1 (rows), 4-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * We must also scale the output by (8/2)*(8/4) = 2**3, which we add here. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]); + tmp1 = GETJSAMPLE(elemptr[1]); + + /* Apply unsigned->signed conversion. */ + dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 3); + + /* Odd part */ + + dataptr[1] = (DCTELEM) ((tmp0 - tmp1) << 3); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ + + dataptr = data; + for (ctr = 0; ctr < 2; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) (tmp0 + tmp1); + dataptr[DCTSIZE*2] = (DCTELEM) (tmp0 - tmp1); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 1x2 sample block. + * + * 1-point FDCT in pass 1 (rows), 2-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_1x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + DCTELEM tmp0, tmp1; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: empty. */ + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/1)*(8/2) = 2**5. + */ + + /* Even part */ + + tmp0 = GETJSAMPLE(sample_data[0][start_col]); + tmp1 = GETJSAMPLE(sample_data[1][start_col]); + + /* Apply unsigned->signed conversion. */ + data[DCTSIZE*0] = (tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5; + + /* Odd part */ + + data[DCTSIZE*1] = (tmp0 - tmp1) << 5; +} + +#endif /* DCT_SCALING_SUPPORTED */ #endif /* DCT_ISLOW_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jidctflt.c b/uppsrc/plugin/jpg/lib/jidctflt.c index 4a89578dc..ce2499f29 100644 --- a/uppsrc/plugin/jpg/lib/jidctflt.c +++ b/uppsrc/plugin/jpg/lib/jidctflt.c @@ -2,6 +2,7 @@ * jidctflt.c * * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2010-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -62,6 +63,8 @@ /* * Perform dequantization and inverse DCT on one block of coefficients. + * + * cK represents cos(K*pi/16). */ GLOBAL(void) @@ -79,7 +82,6 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ @@ -152,12 +154,12 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ + tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + tmp4 = tmp10 - tmp5; wsptr[DCTSIZE*0] = tmp0 + tmp7; wsptr[DCTSIZE*7] = tmp0 - tmp7; @@ -165,8 +167,8 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[DCTSIZE*6] = tmp1 - tmp6; wsptr[DCTSIZE*2] = tmp2 + tmp5; wsptr[DCTSIZE*5] = tmp2 - tmp5; - wsptr[DCTSIZE*4] = tmp3 + tmp4; - wsptr[DCTSIZE*3] = tmp3 - tmp4; + wsptr[DCTSIZE*3] = tmp3 + tmp4; + wsptr[DCTSIZE*4] = tmp3 - tmp4; inptr++; /* advance pointers to next column */ quantptr++; @@ -174,7 +176,6 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, } /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { @@ -187,11 +188,14 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - tmp10 = wsptr[0] + wsptr[4]; - tmp11 = wsptr[0] - wsptr[4]; + /* Prepare range-limit and float->int conversion */ + z5 = wsptr[0] + (((FAST_FLOAT) RANGE_CENTER) + ((FAST_FLOAT) 0.5)); + tmp10 = z5 + wsptr[4]; + tmp11 = z5 - wsptr[4]; tmp13 = wsptr[2] + wsptr[6]; - tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + tmp12 = (wsptr[2] - wsptr[6]) * + ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; @@ -205,35 +209,27 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, z11 = wsptr[1] + wsptr[7]; z12 = wsptr[1] - wsptr[7]; - tmp7 = z11 + z13; - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ + tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ - tmp6 = tmp12 - tmp7; + tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + tmp4 = tmp10 - tmp5; - /* Final output stage: scale down by a factor of 8 and range-limit */ + /* Final output stage: float->int conversion and range-limit */ - outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) - & RANGE_MASK]; + outptr[0] = range_limit[(int) (tmp0 + tmp7) & RANGE_MASK]; + outptr[7] = range_limit[(int) (tmp0 - tmp7) & RANGE_MASK]; + outptr[1] = range_limit[(int) (tmp1 + tmp6) & RANGE_MASK]; + outptr[6] = range_limit[(int) (tmp1 - tmp6) & RANGE_MASK]; + outptr[2] = range_limit[(int) (tmp2 + tmp5) & RANGE_MASK]; + outptr[5] = range_limit[(int) (tmp2 - tmp5) & RANGE_MASK]; + outptr[3] = range_limit[(int) (tmp3 + tmp4) & RANGE_MASK]; + outptr[4] = range_limit[(int) (tmp3 - tmp4) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } diff --git a/uppsrc/plugin/jpg/lib/jidctfst.c b/uppsrc/plugin/jpg/lib/jidctfst.c index 41790ea8c..0c197ced7 100644 --- a/uppsrc/plugin/jpg/lib/jidctfst.c +++ b/uppsrc/plugin/jpg/lib/jidctfst.c @@ -2,6 +2,7 @@ * jidctfst.c * * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -133,35 +134,10 @@ #endif -/* Like DESCALE, but applies to a DCTELEM and produces an int. - * We assume that int right shift is unsigned if INT32 right shift is. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS DCTELEM ishift_temp; -#if BITS_IN_JSAMPLE == 8 -#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ -#else -#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ -#endif -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -#ifdef USE_ACCURATE_ROUNDING -#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) -#else -#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) -#endif - - /* * Perform dequantization and inverse DCT on one block of coefficients. + * + * cK represents cos(K*pi/16). */ GLOBAL(void) @@ -180,7 +156,7 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* for DESCALE */ - ISHIFT_TEMPS /* for IDESCALE */ + ISHIFT_TEMPS /* for IRIGHT_SHIFT */ /* Pass 1: process columns from input, store into work array. */ @@ -196,7 +172,7 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ - + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && @@ -212,13 +188,13 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; - + inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } - + /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); @@ -236,7 +212,7 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; - + /* Odd part */ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); @@ -253,12 +229,12 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + tmp10 = z5 - MULTIPLY(z12, FIX_1_082392200); /* 2*(c2-c6) */ + tmp12 = z5 - MULTIPLY(z10, FIX_2_613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + tmp4 = tmp10 - tmp5; wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); @@ -266,21 +242,28 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); - wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); - wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*4] = (int) (tmp3 - tmp4); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ + + /* Pass 2: process rows from work array, store into output array. + * Note that we must descale the results by a factor of 8 == 2**3, + * and also undo the PASS1_BITS scaling. + */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; + + /* Add range center and fudge factor for final descale and range-limit. */ + z5 = (DCTELEM) wsptr[0] + + ((((DCTELEM) RANGE_CENTER) << (PASS1_BITS+3)) + + (1 << (PASS1_BITS+2))); + /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). @@ -288,14 +271,14 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, * test takes more time than it's worth. In that case this section * may be commented out. */ - + #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + JSAMPLE dcval = range_limit[(int) IRIGHT_SHIFT(z5, PASS1_BITS+3) & RANGE_MASK]; - + outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; @@ -309,15 +292,15 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, continue; } #endif - + /* Even part */ - tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); - tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + tmp10 = z5 + (DCTELEM) wsptr[4]; + tmp11 = z5 - (DCTELEM) wsptr[4]; - tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); - tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) - - tmp13; + tmp13 = (DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]; + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], + FIX_1_414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; @@ -335,30 +318,30 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + tmp10 = z5 - MULTIPLY(z12, FIX_1_082392200); /* 2*(c2-c6) */ + tmp12 = z5 - MULTIPLY(z10, FIX_2_613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + tmp4 = tmp10 - tmp5; /* Final output stage: scale down by a factor of 8 and range-limit */ - outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp7, PASS1_BITS+3) & RANGE_MASK]; - outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + outptr[7] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp7, PASS1_BITS+3) & RANGE_MASK]; - outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp1 + tmp6, PASS1_BITS+3) & RANGE_MASK]; - outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + outptr[6] = range_limit[(int) IRIGHT_SHIFT(tmp1 - tmp6, PASS1_BITS+3) & RANGE_MASK]; - outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + outptr[2] = range_limit[(int) IRIGHT_SHIFT(tmp2 + tmp5, PASS1_BITS+3) & RANGE_MASK]; - outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + outptr[5] = range_limit[(int) IRIGHT_SHIFT(tmp2 - tmp5, PASS1_BITS+3) & RANGE_MASK]; - outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + outptr[3] = range_limit[(int) IRIGHT_SHIFT(tmp3 + tmp4, PASS1_BITS+3) & RANGE_MASK]; - outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + outptr[4] = range_limit[(int) IRIGHT_SHIFT(tmp3 - tmp4, PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ diff --git a/uppsrc/plugin/jpg/lib/jidctint.c b/uppsrc/plugin/jpg/lib/jidctint.c index 63ad6d370..2d7ecdae9 100644 --- a/uppsrc/plugin/jpg/lib/jidctint.c +++ b/uppsrc/plugin/jpg/lib/jidctint.c @@ -2,6 +2,7 @@ * jidctint.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modification developed 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -23,6 +24,28 @@ * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * We also provide IDCT routines with various output sample block sizes for + * direct resolution reduction or enlargement and for direct resolving the + * common 2x1 and 1x2 subsampling cases without additional resampling: NxN + * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 input DCT block. + * + * For N<8 we simply take the corresponding low-frequency coefficients of + * the 8x8 input DCT block and apply an NxN point IDCT on the sub-block + * to yield the downscaled outputs. + * This can be seen as direct low-pass downsampling from the DCT domain + * point of view rather than the usual spatial domain point of view, + * yielding significant computational savings and results at least + * as good as common bilinear (averaging) spatial downsampling. + * + * For N>8 we apply a partial NxN IDCT on the 8 input coefficients as + * lower frequencies and higher frequencies assumed to be zero. + * It turns out that the computational effort is similar to the 8x8 IDCT + * regarding the output size. + * Furthermore, the scaling and descaling is the same for all IDCT sizes. + * + * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases + * since there would be too many additional constants to pre-calculate. */ #define JPEG_INTERNALS @@ -38,7 +61,7 @@ */ #if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ + Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif @@ -142,6 +165,8 @@ /* * Perform dequantization and inverse DCT on one block of coefficients. + * + * cK represents sqrt(2) * cos(K*pi/16). */ GLOBAL(void) @@ -151,7 +176,7 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; + INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; @@ -161,9 +186,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS - /* Pass 1: process columns from input, store into work array. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* Pass 1: process columns from input, store into work array. + * Note results are scaled up by sqrt(8) compared to a true IDCT; + * furthermore, we scale the results by 2**PASS1_BITS. + */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; @@ -200,26 +226,31 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, continue; } - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = z2 + z3; + tmp1 = z2 - z3; z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - - tmp0 = (z2 + z3) << CONST_BITS; - tmp1 = (z2 - z3) << CONST_BITS; - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. @@ -230,52 +261,57 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ + z2 += z1; + z3 += z1; - z3 += z5; - z4 += z5; + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ + /* Pass 2: process rows from work array, store into output array. + * Note that we must descale the results by a factor of 8 == 2**3, + * and also undo the PASS1_BITS scaling. + */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; + + /* Add range center and fudge factor for final descale and range-limit. */ + z2 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). @@ -288,7 +324,7 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + JSAMPLE dcval = range_limit[(int) RIGHT_SHIFT(z2, PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; @@ -305,23 +341,26 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, } #endif - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ + + z3 = (INT32) wsptr[4]; + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[6]; - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ - tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; - tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. @@ -332,58 +371,4869 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp2 = (INT32) wsptr[3]; tmp3 = (INT32) wsptr[1]; - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ + z2 += z1; + z3 += z1; - z3 += z5; - z4 += z5; + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 7x7 output block. + * + * Optimized algorithm with 12 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/14). + */ + +GLOBAL(void) +jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[7*7]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp13 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp13 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp13 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp0 = z1 + z3; + z2 -= tmp0; + tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ + tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + + tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp0 += z2; + tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + wsptr[7*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[7*6] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[7*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[7*5] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[7*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[7*4] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[7*3] = (int) RIGHT_SHIFT(tmp13, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 7 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp13 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp13 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp0 = z1 + z3; + z2 -= tmp0; + tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ + tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + + tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp0 += z2; + tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 7; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 6x6 output block. + * + * Optimized algorithm with 3 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/12). + */ + +GLOBAL(void) +jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); + tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) (tmp11 + tmp1); + wsptr[6*4] = (int) (tmp11 - tmp1); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[6*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[4]; + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = tmp0 - tmp10 - tmp10; + tmp10 = (INT32) wsptr[2]; + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 5x5 output block. + * + * Optimized algorithm with 5 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/10). + */ + +GLOBAL(void) +jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[5*5]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp12 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + wsptr[5*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[5*4] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[5*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[5*3] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[5*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 5 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp12 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp12 <<= CONST_BITS; + tmp0 = (INT32) wsptr[2]; + tmp1 = (INT32) wsptr[4]; + z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 5; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + * + * Optimized algorithm with 3 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[4*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << PASS1_BITS; + tmp12 = (tmp0 - tmp2) << PASS1_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Final output stage */ + + wsptr[4*0] = (int) (tmp10 + tmp0); + wsptr[4*3] = (int) (tmp10 - tmp0); + wsptr[4*1] = (int) (tmp12 + tmp2); + wsptr[4*2] = (int) (tmp12 - tmp2); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp2 = (INT32) wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 3x3 output block. + * + * Optimized algorithm with 2 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/6). + */ + +GLOBAL(void) +jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[3*3]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 3 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[2]; + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = (INT32) wsptr[1]; + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 3; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + * + * Multiplication-less algorithm. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + ISLOW_MULT_TYPE * quantptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + ISHIFT_TEMPS + + /* Pass 1: process columns from input. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + + /* Column 0 */ + tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp4 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); + + tmp0 = tmp4 + tmp5; + tmp2 = tmp4 - tmp5; + + /* Column 1 */ + tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0+1], quantptr[DCTSIZE*0+1]); + tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1+1], quantptr[DCTSIZE*1+1]); + + tmp1 = tmp4 + tmp5; + tmp3 = tmp4 - tmp5; + + /* Pass 2: process 2 rows, store into output array. */ + + /* Row 0 */ + outptr = output_buf[0] + output_col; + + outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; + + /* Row 1 */ + outptr = output_buf[1] + output_col; + + outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp2 + tmp3, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp2 - tmp3, 3) & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + * + * We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + ISHIFT_TEMPS + + /* 1x1 is trivial: just take the DC coefficient divided by 8. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + /* Add range center and fudge factor for descale and range-limit. */ + dcval += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); + + output_buf[0][output_col] = + range_limit[(int) IRIGHT_SHIFT(dcval, 3) & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 9x9 output block. + * + * Optimized algorithm with 10 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/18). + */ + +GLOBAL(void) +jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*9]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ + tmp1 = tmp0 + tmp3; + tmp2 = tmp0 - tmp3 - tmp3; + + tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ + tmp11 = tmp2 + tmp0; + tmp14 = tmp2 - tmp0 - tmp0; + + tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ + tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ + tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ + + tmp10 = tmp1 + tmp0 - tmp3; + tmp12 = tmp1 - tmp0 + tmp2; + tmp13 = tmp1 - tmp2 + tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ + + tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ + tmp0 = tmp2 + tmp3 - z2; + tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ + tmp2 += z2 - tmp1; + tmp3 += z2 + tmp1; + tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 9 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 9; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ + tmp1 = tmp0 + tmp3; + tmp2 = tmp0 - tmp3 - tmp3; + + tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ + tmp11 = tmp2 + tmp0; + tmp14 = tmp2 - tmp0 - tmp0; + + tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ + tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ + tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ + + tmp10 = tmp1 + tmp0 - tmp3; + tmp12 = tmp1 - tmp0 + tmp2; + tmp13 = tmp1 - tmp2 + tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ + + tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ + tmp0 = tmp2 + tmp3 - z2; + tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ + tmp2 += z2 - tmp1; + tmp3 += z2 + tmp1; + tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 10x10 output block. + * + * Optimized algorithm with 12 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/20). + */ + +GLOBAL(void) +jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*10]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + z5 = z3 << CONST_BITS; + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z5 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) (tmp22 + tmp12); + wsptr[8*7] = (int) (tmp22 - tmp12); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 10 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 10; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z3 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[7]; + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z3 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 11x11 output block. + * + * Optimized algorithm with 24 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/22). + */ + +GLOBAL(void) +jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*11]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ + tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ + z4 = z1 + z3; + tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ + z4 -= z2; + tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ + tmp21 = tmp20 + tmp23 + tmp25 - + MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ + tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ + tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ + tmp24 += tmp25; + tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ + tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ + MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ + tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z2; + tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ + tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ + tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ + z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ + tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ + tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ + z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ + tmp11 += z1; + tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ + tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ + MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ + MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 11 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 11; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp10 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp10 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ + tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ + z4 = z1 + z3; + tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ + z4 -= z2; + tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ + tmp21 = tmp20 + tmp23 + tmp25 - + MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ + tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ + tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ + tmp24 += tmp25; + tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ + tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ + MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ + tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z2; + tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ + tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ + tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ + z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ + tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ + tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ + z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ + tmp11 += z1; + tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ + tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ + MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ + MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 12x12 output block. + * + * Optimized algorithm with 15 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/24). + */ + +GLOBAL(void) +jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*12]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 12 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 12; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z3 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z3 <<= CONST_BITS; + + z4 = (INT32) wsptr[4]; + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = (INT32) wsptr[2]; + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = (INT32) wsptr[6]; + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 13x13 output block. + * + * Optimized algorithm with 29 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/26). + */ + +GLOBAL(void) +jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*13]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ + + tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ + tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ + + tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ + tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ + + tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ + tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ + + tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ + tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ + tmp15 = z1 + z4; + tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ + tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ + tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ + tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ + tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ + tmp11 += tmp14; + tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ + tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ + tmp12 += tmp14; + tmp13 += tmp14; + tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ + tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ + MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ + z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ + tmp14 += z1; + tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ + MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 13 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 13; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z1 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z1 <<= CONST_BITS; + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[4]; + z4 = (INT32) wsptr[6]; + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ + + tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ + tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ + + tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ + tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ + + tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ + tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ + + tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ + tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ + tmp15 = z1 + z4; + tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ + tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ + tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ + tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ + tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ + tmp11 += tmp14; + tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ + tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ + tmp12 += tmp14; + tmp13 += tmp14; + tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ + tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ + MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ + z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ + tmp14 += z1; + tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ + MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 14x14 output block. + * + * Optimized algorithm with 20 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/28). + */ + +GLOBAL(void) +jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*14]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp13 = z4 << CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ + tmp16 += tmp15; + z1 += z4; + z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ + tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = (z1 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) (tmp23 + tmp13); + wsptr[8*10] = (int) (tmp23 - tmp13); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 14 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 14; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z1 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z1 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + z4 <<= CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ + tmp16 += tmp15; + tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ + tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = ((z1 - z3) << CONST_BITS) + z4; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 15x15 output block. + * + * Optimized algorithm with 22 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/30). + */ + +GLOBAL(void) +jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*15]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ + tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ + + tmp12 = z1 - tmp10; + tmp13 = z1 + tmp11; + z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ + + z4 = z2 - z3; + z3 += z2; + tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ + z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ + + tmp20 = tmp13 + tmp10 + tmp11; + tmp23 = tmp12 - tmp10 + tmp11 + z2; + + tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ + + tmp25 = tmp13 - tmp10 - tmp11; + tmp26 = tmp12 + tmp10 - tmp11 - z2; + + tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ + + tmp21 = tmp12 + tmp10 + tmp11; + tmp24 = tmp13 - tmp10 + tmp11; + tmp11 += tmp11; + tmp22 = z1 + tmp11; /* c10 = c6-c12 */ + tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp13 = z2 - z4; + tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ + tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ + tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ + + tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ + tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ + z2 = z1 - z4; + tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ + + tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ + tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ + tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ + z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ + tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ + tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 15 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 15; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z1 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z1 <<= CONST_BITS; + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[4]; + z4 = (INT32) wsptr[6]; + + tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ + tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ + + tmp12 = z1 - tmp10; + tmp13 = z1 + tmp11; + z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ + + z4 = z2 - z3; + z3 += z2; + tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ + z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ + + tmp20 = tmp13 + tmp10 + tmp11; + tmp23 = tmp12 - tmp10 + tmp11 + z2; + + tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ + + tmp25 = tmp13 - tmp10 - tmp11; + tmp26 = tmp12 + tmp10 - tmp11 - z2; + + tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ + + tmp21 = tmp12 + tmp10 + tmp11; + tmp24 = tmp13 - tmp10 + tmp11; + tmp11 += tmp11; + tmp22 = z1 + tmp11; /* c10 = c6-c12 */ + tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z4 = (INT32) wsptr[5]; + z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ + z4 = (INT32) wsptr[7]; + + tmp13 = z2 - z4; + tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ + tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ + tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ + + tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ + tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ + z2 = z1 - z4; + tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ + + tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ + tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ + tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ + z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ + tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ + tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 16x16 output block. + * + * Optimized algorithm with 28 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/32). + */ + +GLOBAL(void) +jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*16]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += 1 << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 16 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 16; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[4]; + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 16x8 output block. + * + * 8-point IDCT in pass 1 (columns), 16-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*8]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * Note results are scaled up by sqrt(8) compared to a true IDCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = z2 + z3; + tmp1 = z2 - z3; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process 8 rows from work array, store into output array. + * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[4]; + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 14x7 output block. + * + * 7-point IDCT in pass 1 (columns), 14-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*7]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp23 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp23 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp23 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp10 = z1 + z3; + z2 -= tmp10; + tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ + tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + + tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp10 = tmp11 - tmp12; + tmp11 += tmp12; + tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp11 += tmp12; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp10 += z2; + tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 7 rows from work array, store into output array. + * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z1 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z1 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + z4 <<= CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ + tmp16 += tmp15; + tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ + tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = ((z1 - z3) << CONST_BITS) + z4; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 12x6 output block. + * + * 6-point IDCT in pass 1 (columns), 12-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp12 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ + tmp11 = tmp10 + tmp20; + tmp21 = RIGHT_SHIFT(tmp10 - tmp20 - tmp20, CONST_BITS-PASS1_BITS); + tmp20 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ + tmp20 = tmp11 + tmp10; + tmp22 = tmp11 - tmp10; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); + tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); + tmp11 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) (tmp21 + tmp11); + wsptr[8*4] = (int) (tmp21 - tmp11); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. + * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z3 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z3 <<= CONST_BITS; + + z4 = (INT32) wsptr[4]; + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = (INT32) wsptr[2]; + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = (INT32) wsptr[6]; + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 10x5 output block. + * + * 5-point IDCT in pass 1 (columns), 10-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*5]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp12 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp13 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp14 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp10 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp11 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 5 rows from work array, store into output array. + * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z3 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[7]; + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z3 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 8x4 output block. + * + * 4-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << PASS1_BITS; + tmp12 = (tmp0 - tmp2) << PASS1_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Final output stage */ + + wsptr[8*0] = (int) (tmp10 + tmp0); + wsptr[8*3] = (int) (tmp10 - tmp0); + wsptr[8*1] = (int) (tmp12 + tmp2); + wsptr[8*2] = (int) (tmp12 - tmp2); + } + + /* Pass 2: process rows from work array, store into output array. + * Note that we must descale the results by a factor of 8 == 2**3, + * and also undo the PASS1_BITS scaling. + * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z2 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z3 = (INT32) wsptr[4]; + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 6x3 output block. + * + * 3-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*3]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 3 rows from work array, store into output array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[4]; + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = tmp0 - tmp10 - tmp10; + tmp10 = (INT32) wsptr[2]; + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 4x2 output block. + * + * 2-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + INT32 * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + INT32 workspace[4*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + /* Odd part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + /* Final output stage */ + + wsptr[4*0] = tmp10 + tmp0; + wsptr[4*1] = tmp10 - tmp0; + } + + /* Pass 2: process 2 rows from work array, store into output array. + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = wsptr[0] + ((((INT32) RANGE_CENTER) << 3) + (ONE << 2)); + tmp2 = wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = wsptr[1]; + z3 = wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 2x1 output block. + * + * 1-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1; + ISLOW_MULT_TYPE * quantptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + ISHIFT_TEMPS + + /* Pass 1: empty. */ + + /* Pass 2: process 1 row from input, store into output array. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + outptr = output_buf[0] + output_col; + + /* Even part */ + + tmp0 = DEQUANTIZE(coef_block[0], quantptr[0]); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); + + /* Odd part */ + + tmp1 = DEQUANTIZE(coef_block[1], quantptr[1]); + + /* Final output stage */ + + outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 8x16 output block. + * + * 16-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*16]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process rows from work array, store into output array. + * Note that we must descale the results by a factor of 8 == 2**3, + * and also undo the PASS1_BITS scaling. + * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 16; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ + + /* Add range center and fudge factor for final descale and range-limit. */ + z2 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + z3 = (INT32) wsptr[4]; + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 7x14 output block. + * + * 14-point IDCT in pass 1 (columns), 7-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[7*14]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp13 = z4 << CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ + tmp16 += tmp15; + z1 += z4; + z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ + tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = (z1 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[7*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[7*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[7*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[7*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[7*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[7*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[7*3] = (int) (tmp23 + tmp13); + wsptr[7*10] = (int) (tmp23 - tmp13); + wsptr[7*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[7*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[7*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[7*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[7*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[7*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 14 rows from work array, store into output array. + * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 14; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp23 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp23 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp10 = z1 + z3; + z2 -= tmp10; + tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ + tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + + tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp10 = tmp11 - tmp12; + tmp11 += tmp12; + tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp11 += tmp12; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp10 += z2; + tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 7; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 6x12 output block. + * + * 12-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*12]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[6*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[6*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[6*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[6*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[6*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[6*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[6*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[6*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[6*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 12 rows from work array, store into output array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 12; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp10 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp10 <<= CONST_BITS; + tmp12 = (INT32) wsptr[4]; + tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ + tmp11 = tmp10 + tmp20; + tmp21 = tmp10 - tmp20 - tmp20; + tmp20 = (INT32) wsptr[2]; + tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ + tmp20 = tmp11 + tmp10; + tmp22 = tmp11 - tmp10; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); + tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); + tmp11 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 5x10 output block. + * + * 10-point IDCT in pass 1 (columns), 5-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[5*10]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + z5 = z3 << CONST_BITS; + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z5 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + wsptr[5*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[5*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[5*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[5*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[5*2] = (int) (tmp22 + tmp12); + wsptr[5*7] = (int) (tmp22 - tmp12); + wsptr[5*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[5*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[5*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[5*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 10 rows from work array, store into output array. + * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 10; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp12 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp12 <<= CONST_BITS; + tmp13 = (INT32) wsptr[2]; + tmp14 = (INT32) wsptr[4]; + z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 5; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 4x8 output block. + * + * 8-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[4*8]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * Note results are scaled up by sqrt(8) compared to a true IDCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 4; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[4*0] = dcval; + wsptr[4*1] = dcval; + wsptr[4*2] = dcval; + wsptr[4*3] = dcval; + wsptr[4*4] = dcval; + wsptr[4*5] = dcval; + wsptr[4*6] = dcval; + wsptr[4*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = z2 + z3; + tmp1 = z2 - z3; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[4*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[4*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[4*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[4*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[4*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[4*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[4*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[4*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process 8 rows from work array, store into output array. + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp2 = (INT32) wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 3x6 output block. + * + * 6-point IDCT in pass 1 (columns), 3-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[3*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); + tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*1] = (int) (tmp11 + tmp1); + wsptr[3*4] = (int) (tmp11 - tmp1); + wsptr[3*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[3*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. + * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). + */ + + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[2]; + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = (INT32) wsptr[1]; + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 3; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 2x4 output block. + * + * 4-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + INT32 * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + INT32 workspace[2*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + wsptr[2*0] = tmp10 + tmp0; + wsptr[2*3] = tmp10 - tmp0; + wsptr[2*1] = tmp12 + tmp2; + wsptr[2*2] = tmp12 - tmp2; + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add range center and fudge factor for final descale and range-limit. */ + tmp10 = wsptr[0] + + ((((INT32) RANGE_CENTER) << (CONST_BITS+3)) + + (ONE << (CONST_BITS+2))); + + /* Odd part */ + + tmp0 = wsptr[1]; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+3) + & RANGE_MASK]; + + wsptr += 2; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 1x2 output block. + * + * 2-point IDCT in pass 1 (columns), 1-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + ISHIFT_TEMPS + + /* Process 1 column from input, store into output array. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + + /* Even part */ + + tmp0 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); + + /* Odd part */ + + tmp1 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); + + /* Final output stage */ + + output_buf[0][output_col] = + range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; + output_buf[1][output_col] = + range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ #endif /* DCT_ISLOW_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jidctred.c b/uppsrc/plugin/jpg/lib/jidctred.c deleted file mode 100644 index 6a923f455..000000000 --- a/uppsrc/plugin/jpg/lib/jidctred.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * jidctred.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains inverse-DCT routines that produce reduced-size output: - * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. - * - * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) - * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step - * with an 8-to-4 step that produces the four averages of two adjacent outputs - * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). - * These steps were derived by computing the corresponding values at the end - * of the normal LL&M code, then simplifying as much as possible. - * - * 1x1 is trivial: just take the DC coefficient divided by 8. - * - * See jidctint.c for additional comments. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef IDCT_SCALING_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling is the same as in jidctint.c. */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ -#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ -#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ -#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ -#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ -#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ -#else -#define FIX_0_211164243 FIX(0.211164243) -#define FIX_0_509795579 FIX(0.509795579) -#define FIX_0_601344887 FIX(0.601344887) -#define FIX_0_720959822 FIX(0.720959822) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_850430095 FIX(0.850430095) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_061594337 FIX(1.061594337) -#define FIX_1_272758580 FIX(1.272758580) -#define FIX_1_451774981 FIX(1.451774981) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_2_172734803 FIX(2.172734803) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_624509785 FIX(3.624509785) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - -#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 4x4 output block. - */ - -GLOBAL(void) -jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp2, tmp10, tmp12; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE*4]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process column 4, because second pass won't use it */ - if (ctr == DCTSIZE-4) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && - inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine term 4 for 4x4 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= (CONST_BITS+1); - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); - - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ - + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ - + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ - + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ - + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ - + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ - + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); - } - - /* Pass 2: process 4 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); - - tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) - + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); - - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - - /* Odd part */ - - z1 = (INT32) wsptr[7]; - z2 = (INT32) wsptr[5]; - z3 = (INT32) wsptr[3]; - z4 = (INT32) wsptr[1]; - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ - + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ - + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ - + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ - + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ - + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ - + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 2x2 output block. - */ - -GLOBAL(void) -jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp10, z1; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE*2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process columns 2,4,6 */ - if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - - continue; - } - - /* Even part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp10 = z1 << (CONST_BITS+2); - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); - } - - /* Pass 2: process 2 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 2; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); - - /* Odd part */ - - tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ - + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ - + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ - + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 1x1 output block. - */ - -GLOBAL(void) -jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - int dcval; - ISLOW_MULT_TYPE * quantptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - SHIFT_TEMPS - - /* We hardly need an inverse DCT routine for this: just take the - * average pixel value, which is one-eighth of the DC coefficient. - */ - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - dcval = DEQUANTIZE(coef_block[0], quantptr[0]); - dcval = (int) DESCALE((INT32) dcval, 3); - - output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; -} - -#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/jlossls.h b/uppsrc/plugin/jpg/lib/jlossls.h deleted file mode 100644 index eff1d7094..000000000 --- a/uppsrc/plugin/jpg/lib/jlossls.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * jlossls.h - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file contains common declarations for the lossless JPEG - * codec modules. - */ - -#ifndef JLOSSLS_H -#define JLOSSLS_H - - -/* - * Table H.1: Predictors for lossless coding. - */ - -#define PREDICTOR1 Ra -#define PREDICTOR2 Rb -#define PREDICTOR3 Rc -#define PREDICTOR4 (int) ((INT32) Ra + (INT32) Rb - (INT32) Rc) -#define PREDICTOR5 (int) ((INT32) Ra + RIGHT_SHIFT((INT32) Rb - (INT32) Rc, 1)) -#define PREDICTOR6 (int) ((INT32) Rb + RIGHT_SHIFT((INT32) Ra - (INT32) Rc, 1)) -#define PREDICTOR7 (int) RIGHT_SHIFT((INT32) Ra + (INT32) Rb, 1) - - -typedef JMETHOD(void, predict_difference_method_ptr, - (j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW prev_row, - JDIFFROW diff_buf, JDIMENSION width)); - -typedef JMETHOD(void, scaler_method_ptr, - (j_compress_ptr cinfo, int ci, - JSAMPROW input_buf, JSAMPROW output_buf, - JDIMENSION width)); - -/* Lossless-specific compression codec (compressor proper) */ -typedef struct { - struct jpeg_c_codec pub; /* public fields */ - - - /* Difference buffer control */ - JMETHOD(void, diff_start_pass, (j_compress_ptr cinfo, - J_BUF_MODE pass_mode)); - - /* Pointer to data which is private to diff controller */ - void *diff_private; - - - /* Entropy encoding */ - JMETHOD(JDIMENSION, entropy_encode_mcus, (j_compress_ptr cinfo, - JDIFFIMAGE diff_buf, - JDIMENSION MCU_row_num, - JDIMENSION MCU_col_num, - JDIMENSION nMCU)); - - /* Pointer to data which is private to entropy module */ - void *entropy_private; - - - /* Prediction, differencing */ - JMETHOD(void, predict_start_pass, (j_compress_ptr cinfo)); - - /* It is useful to allow each component to have a separate diff method. */ - predict_difference_method_ptr predict_difference[MAX_COMPONENTS]; - - /* Pointer to data which is private to predictor module */ - void *pred_private; - - /* Sample scaling */ - JMETHOD(void, scaler_start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, scaler_scale, (j_compress_ptr cinfo, - JSAMPROW input_buf, JSAMPROW output_buf, - JDIMENSION width)); - - /* Pointer to data which is private to scaler module */ - void *scaler_private; - -} jpeg_lossless_c_codec; - -typedef jpeg_lossless_c_codec * j_lossless_c_ptr; - - -typedef JMETHOD(void, predict_undifference_method_ptr, - (j_decompress_ptr cinfo, int comp_index, - JDIFFROW diff_buf, JDIFFROW prev_row, - JDIFFROW undiff_buf, JDIMENSION width)); - -/* Lossless-specific decompression codec (decompressor proper) */ -typedef struct { - struct jpeg_d_codec pub; /* public fields */ - - - /* Difference buffer control */ - JMETHOD(void, diff_start_input_pass, (j_decompress_ptr cinfo)); - - /* Pointer to data which is private to diff controller */ - void *diff_private; - - - /* Entropy decoding */ - JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo)); - JMETHOD(boolean, entropy_process_restart, (j_decompress_ptr cinfo)); - JMETHOD(JDIMENSION, entropy_decode_mcus, (j_decompress_ptr cinfo, - JDIFFIMAGE diff_buf, - JDIMENSION MCU_row_num, - JDIMENSION MCU_col_num, - JDIMENSION nMCU)); - - /* Pointer to data which is private to entropy module */ - void *entropy_private; - - - /* Prediction, undifferencing */ - JMETHOD(void, predict_start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, predict_process_restart, (j_decompress_ptr cinfo)); - - /* It is useful to allow each component to have a separate undiff method. */ - predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS]; - - /* Pointer to data which is private to predictor module */ - void *pred_private; - - /* Sample scaling */ - JMETHOD(void, scaler_start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, scaler_scale, (j_decompress_ptr cinfo, - JDIFFROW diff_buf, JSAMPROW output_buf, - JDIMENSION width)); - - /* Pointer to data which is private to scaler module */ - void *scaler_private; - -} jpeg_lossless_d_codec; - -typedef jpeg_lossless_d_codec * j_lossless_d_ptr; - - -/* Compression module initialization routines */ -EXTERN(void) jinit_lhuff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_differencer JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_c_scaler JPP((j_compress_ptr cinfo)); -/* Decompression module initialization routines */ -EXTERN(void) jinit_lhuff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_undifferencer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_d_scaler JPP((j_decompress_ptr cinfo)); - -#endif /* JLOSSLS_H */ diff --git a/uppsrc/plugin/jpg/lib/jlossy.h b/uppsrc/plugin/jpg/lib/jlossy.h deleted file mode 100644 index f9241c9d7..000000000 --- a/uppsrc/plugin/jpg/lib/jlossy.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * jlossy.h - * - * Copyright (C) 1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file contains common declarations for the lossy (DCT-based) - * JPEG codec modules. - */ - -#ifndef JLOSSY_H -#define JLOSSY_H - - -/* Lossy-specific compression codec (compressor proper) */ -typedef struct { - struct jpeg_c_codec pub; /* public fields */ - - - /* Coefficient buffer control */ - JMETHOD(void, coef_start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - /* JMETHOD(boolean, coef_compress_data, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf));*/ - - /* Pointer to data which is private to coef module */ - void *coef_private; - - - /* Forward DCT (also controls coefficient quantization) */ - JMETHOD(void, fdct_start_pass, (j_compress_ptr cinfo)); - /* perhaps this should be an array??? */ - JMETHOD(void, fdct_forward_DCT, (j_compress_ptr cinfo, - jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); - - /* Pointer to data which is private to fdct module */ - void *fdct_private; - - - /* Entropy encoding */ - JMETHOD(boolean, entropy_encode_mcu, (j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); - - /* Pointer to data which is private to entropy module */ - void *entropy_private; - -} jpeg_lossy_c_codec; - -typedef jpeg_lossy_c_codec * j_lossy_c_ptr; - - - -typedef JMETHOD(void, inverse_DCT_method_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col)); - -/* Lossy-specific decompression codec (decompressor proper) */ -typedef struct { - struct jpeg_d_codec pub; /* public fields */ - - - /* Coefficient buffer control */ - JMETHOD(void, coef_start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, coef_start_output_pass, (j_decompress_ptr cinfo)); - - /* Pointer to array of coefficient virtual arrays, or NULL if none */ - jvirt_barray_ptr *coef_arrays; - - /* Pointer to data which is private to coef module */ - void *coef_private; - - - /* Entropy decoding */ - JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo)); - JMETHOD(boolean, entropy_decode_mcu, (j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); - - /* This is here to share code between baseline and progressive decoders; */ - /* other modules probably should not use it */ - boolean entropy_insufficient_data; /* set TRUE after emitting warning */ - - /* Pointer to data which is private to entropy module */ - void *entropy_private; - - - /* Inverse DCT (also performs dequantization) */ - JMETHOD(void, idct_start_pass, (j_decompress_ptr cinfo)); - - /* It is useful to allow each component to have a separate IDCT method. */ - inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; - - /* Pointer to data which is private to idct module */ - void *idct_private; - -} jpeg_lossy_d_codec; - -typedef jpeg_lossy_d_codec * j_lossy_d_ptr; - - -/* Compression module initialization routines */ -EXTERN(void) jinit_lossy_c_codec JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_shuff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); - -/* Decompression module initialization routines */ -EXTERN(void) jinit_lossy_d_codec JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_shuff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); - -#endif /* JLOSSY_H */ diff --git a/uppsrc/plugin/jpg/lib/jmemdos.c b/uppsrc/plugin/jpg/lib/jmemdos.c index b2d13d8b0..0955047ec 100644 --- a/uppsrc/plugin/jpg/lib/jmemdos.c +++ b/uppsrc/plugin/jpg/lib/jmemdos.c @@ -228,7 +228,7 @@ jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, * 2. Extended memory, accessed per the XMS V2.0 specification. * 3. Expanded memory, accessed per the LIM/EMS 4.0 specification. * You'll need copies of those specs to make sense of the related code. - * The specs are available by Internet FTP from the SIMTEL archives + * The specs are available by Internet FTP from the SIMTEL archives * (oak.oakland.edu and its various mirror sites). See files * pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip. */ @@ -347,7 +347,7 @@ read_xms_store (j_common_ptr cinfo, backing_store_ptr info, spec.src.offset = file_offset; spec.dst_handle = 0; spec.dst.ptr = buffer_address; - + ctx.ds_si = (void far *) & spec; ctx.ax = 0x0b00; /* EMB move */ jxms_calldriver(xms_driver, (XMScontext far *) & ctx); @@ -503,7 +503,7 @@ read_ems_store (j_common_ptr cinfo, backing_store_ptr info, DST_TYPE(spec) = 0; DST_HANDLE(spec) = 0; DST_PTR(spec) = buffer_address; - + ctx.ds_si = (void far *) & spec; ctx.ax = 0x5700; /* move memory region */ jems_calldriver((EMScontext far *) & ctx); @@ -528,7 +528,7 @@ write_ems_store (j_common_ptr cinfo, backing_store_ptr info, DST_HANDLE(spec) = info->handle.ems_handle; DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); - + ctx.ds_si = (void far *) & spec; ctx.ax = 0x5700; /* move memory region */ jems_calldriver((EMScontext far *) & ctx); diff --git a/uppsrc/plugin/jpg/lib/jmemmgr.c b/uppsrc/plugin/jpg/lib/jmemmgr.c index 01f209bd9..ea9342022 100644 --- a/uppsrc/plugin/jpg/lib/jmemmgr.c +++ b/uppsrc/plugin/jpg/lib/jmemmgr.c @@ -1,7 +1,8 @@ /* * jmemmgr.c * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2011-2012 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -42,12 +43,11 @@ extern char * getenv JPP((const char * name)); * The allocation routines provided here must never return NULL. * They should exit to error_exit if unsuccessful. * - * It's not a good idea to try to merge the sarray, barray and darray - * routines, even though they are textually almost the same, because - * samples are usually stored as bytes while coefficients and differenced - * are shorts or ints. Thus, in machines where byte pointers have a - * different representation from word pointers, the resulting machine - * code could not be the same. + * It's not a good idea to try to merge the sarray and barray routines, + * even though they are textually almost the same, because samples are + * usually stored as bytes while coefficients are shorts or ints. Thus, + * in machines where byte pointers have a different representation from + * word pointers, the resulting machine code could not be the same. */ @@ -214,7 +214,7 @@ print_mem_stats (j_common_ptr cinfo, int pool_id) #endif /* MEM_STATS */ -LOCAL(void) +LOCAL(noreturn_t) out_of_memory (j_common_ptr cinfo, int which) /* Report an out-of-memory error and stop execution */ /* If we compiled MEM_STATS support, report alloc requests before dying */ @@ -239,13 +239,13 @@ out_of_memory (j_common_ptr cinfo, int which) * machines, but may be too small if longs are 64 bits or more. */ -static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = { 1600, /* first PERMANENT pool */ 16000 /* first IMAGE pool */ }; -static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = { 0, /* additional PERMANENT pools */ 5000 /* additional IMAGE pools */ @@ -483,58 +483,6 @@ alloc_barray (j_common_ptr cinfo, int pool_id, } -#ifdef NEED_DARRAY - -/* - * Creation of 2-D difference arrays. - * This is essentially the same as the code for sample arrays, above. - */ - -METHODDEF(JDIFFARRAY) -alloc_darray (j_common_ptr cinfo, int pool_id, - JDIMENSION diffsperrow, JDIMENSION numrows) -/* Allocate a 2-D difference array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JDIFFARRAY result; - JDIFFROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) diffsperrow * SIZEOF(JDIFF)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JDIFFARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JDIFFROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JDIFFROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) diffsperrow - * SIZEOF(JDIFF))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += diffsperrow; - } - } - - return result; -} - -#endif - - /* * About virtual array management: * @@ -874,7 +822,7 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { - jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; } } else { @@ -959,7 +907,7 @@ access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { - jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; } } else { @@ -1121,9 +1069,6 @@ jinit_memory_mgr (j_common_ptr cinfo) mem->pub.alloc_large = alloc_large; mem->pub.alloc_sarray = alloc_sarray; mem->pub.alloc_barray = alloc_barray; -#ifdef NEED_DARRAY - mem->pub.alloc_darray = alloc_darray; -#endif mem->pub.request_virt_sarray = request_virt_sarray; mem->pub.request_virt_barray = request_virt_barray; mem->pub.realize_virt_arrays = realize_virt_arrays; diff --git a/uppsrc/plugin/jpg/lib/jmorecfg.h b/uppsrc/plugin/jpg/lib/jmorecfg.h index 0d2814f26..7407ac79b 100644 --- a/uppsrc/plugin/jpg/lib/jmorecfg.h +++ b/uppsrc/plugin/jpg/lib/jmorecfg.h @@ -1,7 +1,8 @@ /* * jmorecfg.h * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -14,13 +15,22 @@ /* * Define BITS_IN_JSAMPLE as either * 8 for 8-bit sample values (the usual setting) + * 9 for 9-bit sample values + * 10 for 10-bit sample values + * 11 for 11-bit sample values * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. + * Only 8, 9, 10, 11, and 12 bits sample data precision are supported for + * full-feature DCT processing. Further depths up to 16-bit may be added + * later for the lossless modes of operation. + * Run-time selection and conversion of data precision will be added later + * and are currently not supported, sorry. + * Exception: The transcoding part (jpegtran) supports all settings in a + * single instance, since it operates on the level of DCT coefficients and + * not sample values. The DCT coefficients are of the same type (16 bits) + * in all cases (see below). */ -#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ +#define BITS_IN_JSAMPLE 8 /* use 8, 9, 10, 11, or 12 */ /* @@ -76,6 +86,48 @@ typedef char JSAMPLE; #endif /* BITS_IN_JSAMPLE == 8 */ +#if BITS_IN_JSAMPLE == 9 +/* JSAMPLE should be the smallest type that will hold the values 0..511. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 511 +#define CENTERJSAMPLE 256 + +#endif /* BITS_IN_JSAMPLE == 9 */ + + +#if BITS_IN_JSAMPLE == 10 +/* JSAMPLE should be the smallest type that will hold the values 0..1023. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 1023 +#define CENTERJSAMPLE 512 + +#endif /* BITS_IN_JSAMPLE == 10 */ + + +#if BITS_IN_JSAMPLE == 11 +/* JSAMPLE should be the smallest type that will hold the values 0..2047. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 2047 +#define CENTERJSAMPLE 1024 + +#endif /* BITS_IN_JSAMPLE == 11 */ + + #if BITS_IN_JSAMPLE == 12 /* JSAMPLE should be the smallest type that will hold the values 0..4095. * On nearly all machines "short" will do nicely. @@ -90,33 +142,6 @@ typedef short JSAMPLE; #endif /* BITS_IN_JSAMPLE == 12 */ -#if BITS_IN_JSAMPLE == 16 -/* JSAMPLE should be the smallest type that will hold the values 0..65535. - * You can use a signed short by having GETJSAMPLE mask it with 0xFFFF. - */ - -#ifdef HAVE_UNSIGNED_SHORT - -typedef unsigned short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#else /* not HAVE_UNSIGNED_SHORT */ - -typedef short JSAMPLE; -#ifdef SHORT_IS_UNSIGNED -#define GETJSAMPLE(value) ((int) (value)) -#else -#define GETJSAMPLE(value) ((int) (value) & 0xFFFF) -#endif /* SHORT_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_SHORT */ - -#define MAXJSAMPLE 65535 -#define CENTERJSAMPLE 32768 - -#endif /* BITS_IN_JSAMPLE == 16 */ - - /* Representation of a DCT frequency coefficient. * This should be a signed value of at least 16 bits; "short" is usually OK. * Again, we allocate large arrays of these, but you can change to int @@ -126,13 +151,6 @@ typedef short JSAMPLE; typedef short JCOEF; -/* Representation of a spatial difference value. - * This should be a signed value of at least 16 bits; int is usually OK. - */ - -typedef int JDIFF; - - /* Compressed datastreams are represented as arrays of JOCTET. * These must be EXACTLY 8 bits wide, at least once they are written to * external storage. Note that when using the stdio data source/destination @@ -191,9 +209,15 @@ typedef short INT16; /* INT32 must hold at least signed 32-bit values. */ -#if !defined(XMD_H) && !defined(_BASETSD_H) && !defined(_BASETSD_H_) /* X11/xmd.h correctly defines INT32 */ +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ typedef long INT32; #endif +#endif +#endif +#endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore @@ -237,17 +261,39 @@ typedef unsigned int JDIMENSION; #endif +/* The noreturn type identifier is used to declare functions + * which cannot return. + * Compilers can thus create more optimized code and perform + * better checks for warnings and errors. + * Static analyzer tools can make improved inferences about + * execution paths and are prevented from giving false alerts. + * + * Unfortunately, the proposed specifications of corresponding + * extensions in the Dec 2011 ISO C standard revision (C11), + * GCC, MSVC, etc. are not viable. + * Thus we introduce a user defined type to declare noreturn + * functions at least for clarity. A proper compiler would + * have a suitable noreturn type to match in place of void. + */ + +#ifndef HAVE_NORETURN_T +typedef void noreturn_t; +#endif + + /* Here is the pseudo-keyword for declaring pointers that must be "far" * on 80x86 machines. Most of the specialized coding for 80x86 is handled * by just saying "FAR *" where such a pointer is needed. In a few places * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ +#ifndef FAR #ifdef NEED_FAR_POINTERS #define FAR far #else #define FAR #endif +#endif /* @@ -258,17 +304,19 @@ typedef unsigned int JDIMENSION; */ #ifndef HAVE_BOOLEAN -#ifdef boolean -#undef boolean -#endif -#define boolean int -#endif +#if defined FALSE || defined TRUE || defined QGLOBAL_H +/* Qt3 defines FALSE and TRUE as "const" variables in qglobal.h */ +typedef int boolean; #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif +#else +typedef enum { FALSE = 0, TRUE = 1 } boolean; +#endif +#endif /* @@ -293,8 +341,6 @@ typedef unsigned int JDIMENSION; * (You may HAVE to do that if your compiler doesn't like null source files.) */ -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - /* Capability options common to encoder and decoder: */ #define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ @@ -303,31 +349,30 @@ typedef unsigned int JDIMENSION; /* Encoder capability options: */ -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected 12-bit data precision, it is dangerous to turn off - * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit - * precision, so jcshuff.c normally uses entropy optimization to compute - * usable tables for higher precision. If you don't want to do optimization, - * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive and lossless JPEG: - * the default tables don't work for progressive mode or lossless mode. - * (This may get fixed, however.) +/* Note: if you selected more than 8-bit data precision, it is dangerous to + * turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only + * good for 8-bit precision, so arithmetic coding is recommended for higher + * precision. The Huffman encoder normally uses entropy optimization to + * compute usable tables for higher precision. Otherwise, you'll have to + * supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) */ #define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ /* Decoder capability options: */ -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ #define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ @@ -344,9 +389,7 @@ typedef unsigned int JDIMENSION; * the offsets will also change the order in which colormap data is organized. * RESTRICTIONS: * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. - * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not - * useful if you are using JPEG color spaces other than YCbCr or grayscale. - * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE * is not 3 (they don't understand about dummy color components!). So you * can't use color quantization if you change that value. */ diff --git a/uppsrc/plugin/jpg/lib/jpegint.h b/uppsrc/plugin/jpg/lib/jpegint.h index 5f5a20e10..ec14a1ebc 100644 --- a/uppsrc/plugin/jpg/lib/jpegint.h +++ b/uppsrc/plugin/jpg/lib/jpegint.h @@ -1,7 +1,8 @@ /* * jpegint.h * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -72,12 +73,8 @@ struct jpeg_c_prep_controller { JDIMENSION out_row_groups_avail)); }; -/* Compression codec (compressor proper) */ -struct jpeg_c_codec { - JMETHOD(void, entropy_start_pass, (j_compress_ptr cinfo, - boolean gather_statistics)); - JMETHOD(void, entropy_finish_pass, (j_compress_ptr cinfo)); - JMETHOD(boolean, need_optimization_pass, (j_compress_ptr cinfo)); +/* Coefficient buffer control */ +struct jpeg_c_coef_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, JSAMPIMAGE input_buf)); @@ -102,6 +99,26 @@ struct jpeg_downsampler { boolean need_context_rows; /* TRUE if need rows above & below */ }; +/* Forward DCT (also controls coefficient quantization) */ +typedef JMETHOD(void, forward_DCT_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); + +struct jpeg_forward_dct { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + /* It is useful to allow each component to have a separate FDCT method. */ + forward_DCT_ptr forward_DCT[MAX_COMPONENTS]; +}; + +/* Entropy encoding */ +struct jpeg_entropy_encoder { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); + JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); +}; + /* Marker writing */ struct jpeg_marker_writer { JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); @@ -148,14 +165,15 @@ struct jpeg_d_main_controller { JDIMENSION out_rows_avail)); }; -/* Decompression codec (decompressor proper) */ -struct jpeg_d_codec { - JMETHOD(void, calc_output_dimensions, (j_decompress_ptr cinfo)); +/* Coefficient buffer control */ +struct jpeg_d_coef_controller { JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; }; /* Decompression postprocessing (color quantization buffer control) */ @@ -190,6 +208,25 @@ struct jpeg_marker_reader { unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ }; +/* Entropy decoding */ +struct jpeg_entropy_decoder { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); +}; + +/* Inverse DCT (also performs dequantization) */ +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +struct jpeg_inverse_dct { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; +}; + /* Upsampling (note that upsampler must also call color converter) */ struct jpeg_upsampler { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); @@ -256,8 +293,6 @@ struct jpeg_color_quantizer { /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_c_codec jICCodec -#define jinit_lossy_c_codec jILossyC #define jinit_compress_master jICompress #define jinit_c_master_control jICMaster #define jinit_c_main_controller jICMainC @@ -266,24 +301,17 @@ struct jpeg_color_quantizer { #define jinit_color_converter jICColor #define jinit_downsampler jIDownsampler #define jinit_forward_dct jIFDCT -#define jinit_shuff_encoder jISHEncoder -#define jinit_phuff_encoder jIPHEncoder +#define jinit_huff_encoder jIHEncoder +#define jinit_arith_encoder jIAEncoder #define jinit_marker_writer jIMWriter -#define jinit_d_codec jIDCodec -#define jinit_lossy_d_codec jILossyD -#define jinit_lossless_d_codec jILosslsD #define jinit_master_decompress jIDMaster #define jinit_d_main_controller jIDMainC #define jinit_d_coef_controller jIDCoefC -#define jinit_d_diff_controller jIDDiffC #define jinit_d_post_controller jIDPostC #define jinit_input_controller jIInCtlr #define jinit_marker_reader jIMReader -#define jinit_shuff_decoder jISHDecoder -#define jinit_phuff_decoder jIPHDecoder -#define jinit_lhuff_decoder jILHDecoder -#define jinit_undifferencer jIUndiff -#define jinit_d_scaler jIDScaler +#define jinit_huff_decoder jIHDecoder +#define jinit_arith_decoder jIADecoder #define jinit_inverse_dct jIIDCT #define jinit_upsampler jIUpsampler #define jinit_color_deconverter jIDColor @@ -293,41 +321,70 @@ struct jpeg_color_quantizer { #define jinit_memory_mgr jIMemMgr #define jdiv_round_up jDivRound #define jround_up jRound +#define jzero_far jZeroFar #define jcopy_sample_rows jCopySamples #define jcopy_block_row jCopyBlocks -#define jzero_far jZeroFar #define jpeg_zigzag_order jZIGTable #define jpeg_natural_order jZAGTable +#define jpeg_natural_order7 jZAG7Table +#define jpeg_natural_order6 jZAG6Table +#define jpeg_natural_order5 jZAG5Table +#define jpeg_natural_order4 jZAG4Table +#define jpeg_natural_order3 jZAG3Table +#define jpeg_natural_order2 jZAG2Table +#define jpeg_aritab jAriTab #endif /* NEED_SHORT_EXTERNAL_NAMES */ +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines in jutils.c do it the hard way. + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */ +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case */ +#ifdef USE_FMEM +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#else +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +#define FMEMZERO(target,size) jzero_far(target, size) +#endif +#endif + + /* Compression module initialization routines */ EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, boolean transcode_only)); -EXTERN(void) jinit_c_codec JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_lossless_c_codec JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_c_diff_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); -EXTERN(void) jinit_compressor JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); /* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); -EXTERN(void) jinit_d_codec JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_lossless_d_codec JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_d_diff_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); -EXTERN(void) jinit_decompressor JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); @@ -344,12 +401,20 @@ EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, int num_rows, JDIMENSION num_cols)); EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks)); -EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); /* Constant tables in jutils.c */ #if 0 /* This table is not actually needed in v6a */ extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ #endif extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ +extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ +extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ +extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ +extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ +extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ +extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ + +/* Arithmetic coding probability estimation tables in jaricom.c */ +extern const INT32 jpeg_aritab[]; /* Suppress undefined-structure complaints if necessary. */ diff --git a/uppsrc/plugin/jpg/lib/jpeglib.h b/uppsrc/plugin/jpg/lib/jpeglib.h index 65849aaca..20ef353d8 100644 --- a/uppsrc/plugin/jpg/lib/jpeglib.h +++ b/uppsrc/plugin/jpg/lib/jpeglib.h @@ -2,6 +2,7 @@ * jpeglib.h * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -26,19 +27,27 @@ #include "jmorecfg.h" /* seldom changed options */ -/* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + +/* Version IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 90". */ -#define JPEG_LIB_VERSION 62 /* Version 6b */ +#define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */ +#define JPEG_LIB_VERSION_MAJOR 9 +#define JPEG_LIB_VERSION_MINOR 2 /* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, so don't change them - * if you want to be compatible. + * All of these are specified by the JPEG standard, + * so don't change them if you want to be compatible. */ -#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ #define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ @@ -46,16 +55,15 @@ #define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ #define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ /* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; - * the PostScript DCT filter can emit files with many more than 10 data units - * per MCU. - * If you happen to run across such a file, you can up D_MAX_DATA_UNITS_IN_MCU + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU * to handle it. We even let you do this from the jconfig.h file. However, - * we strongly discourage changing C_MAX_DATA_UNITS_IN_MCU; just because Adobe + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe * sometimes emits noncompliant files doesn't mean you should too. */ -#define C_MAX_DATA_UNITS_IN_MCU 10 /* compressor's limit on data units/MCU */ -#ifndef D_MAX_DATA_UNITS_IN_MCU -#define D_MAX_DATA_UNITS_IN_MCU 10 /* decompressor's limit on data units/MCU */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ #endif @@ -75,10 +83,6 @@ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ -typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */ -typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */ -typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */ - /* Types for JPEG compression parameters and working tables. */ @@ -133,47 +137,50 @@ typedef struct { /* The decompressor output side may not use these variables. */ int dc_tbl_no; /* DC entropy table selector (0..3) */ int ac_tbl_no; /* AC entropy table selector (0..3) */ - + /* Remaining fields should be treated as private by applications. */ - + /* These values are computed during compression or decompression startup: */ - /* Component's size in data units. - * Any dummy data units added to complete an MCU are not counted; therefore + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore * these values do not depend on whether a scan is interleaved or not. */ - JDIMENSION width_in_data_units; - JDIMENSION height_in_data_units; - /* Size of a data unit in/output by the codec (in samples). Always - * data_unit for compression. For decompression this is the size of the - * output from one data_unit, reflecting any processing performed by the - * codec. For example, in the DCT-based codec, scaling may be applied - * during the IDCT step. Values of 1,2,4,8 are likely to be supported. - * Note that different components may have different codec_data_unit sizes. + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. */ - int codec_data_unit; + int DCT_h_scaled_size; + int DCT_v_scaled_size; /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface), thus - * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, codec-based processing is - * included (ie, IDCT scaling), so - * downsampled_width = ceil(image_width * Hi/Hmax * codec_data_unit/data_unit) + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = + * ceil(image_width * Hi/Hmax * DCT_h_scaled_size/block_size) + * and similarly for height. */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ - /* This flag is used only for decompression. In cases where some of the - * components will be ignored (eg grayscale output from YCbCr image), - * we can skip most computations for the unused components. + /* For decompression, in cases where some of the components will be + * ignored (eg grayscale output from YCbCr image), we can skip most + * computations for the unused components. + * For compression, some of the components will need further quantization + * scale by factor of 2 after DCT (eg BG_YCC output from normal RGB input). + * The field is first set TRUE for decompression, FALSE for compression + * in initial_setup, and then adapted in color conversion setup. */ - boolean component_needed; /* do we need the value of this component? */ + boolean component_needed; /* These values are computed before starting a scan of the component. */ /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of data units per MCU, horizontally */ - int MCU_height; /* number of data units per MCU, vertically */ - int MCU_data_units; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples, MCU_width*codec_data_unit */ - int last_col_width; /* # of non-dummy data_units across in last MCU */ - int last_row_height; /* # of non-dummy data_units down in last MCU */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ /* Saved quantization table for component; NULL if none yet saved. * See jdinput.c comments about the need for this information. @@ -191,10 +198,8 @@ typedef struct { typedef struct { int comps_in_scan; /* number of components encoded in this scan */ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms - lossless JPEG predictor select parm (Ss) */ - int Ah, Al; /* progressive JPEG successive approx. parms - lossless JPEG point transform parm (Al) */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ } jpeg_scan_info; /* The decompressor can save APPn and COM markers in a list of these: */ @@ -210,25 +215,26 @@ struct jpeg_marker_struct { /* the marker length word is not counted in data_length or original_length */ }; -/* Known codec processes. */ - -typedef enum { - JPROC_SEQUENTIAL, /* baseline/extended sequential DCT */ - JPROC_PROGRESSIVE, /* progressive DCT */ - JPROC_LOSSLESS /* lossless (sequential) */ -} J_CODEC_PROCESS; - /* Known color spaces. */ typedef enum { JCS_UNKNOWN, /* error/unspecified */ JCS_GRAYSCALE, /* monochrome */ - JCS_RGB, /* red/green/blue */ - JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_RGB, /* red/green/blue, standard RGB (sRGB) */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV), standard YCC */ JCS_CMYK, /* C/M/Y/K */ - JCS_YCCK /* Y/Cb/Cr/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_BG_RGB, /* big gamut red/green/blue, bg-sRGB */ + JCS_BG_YCC /* big gamut Y/Cb/Cr, bg-sYCC */ } J_COLOR_SPACE; +/* Supported color transforms. */ + +typedef enum { + JCT_NONE = 0, + JCT_SUBTRACT_GREEN = 1 +} J_COLOR_TRANSFORM; + /* DCT/IDCT algorithm options. */ typedef enum { @@ -308,7 +314,16 @@ struct jpeg_compress_struct { * helper routines to simplify changing parameters. */ - boolean lossless; /* TRUE=lossless encoding, FALSE=lossy */ + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ int data_precision; /* bits of precision in image data */ @@ -319,7 +334,10 @@ struct jpeg_compress_struct { /* comp_info[i] describes component that appears i'th in SOF */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; @@ -340,6 +358,7 @@ struct jpeg_compress_struct { boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ int smoothing_factor; /* 1..100, or 0 for no input smoothing */ J_DCT_METHOD dct_method; /* DCT algorithm selector */ @@ -365,6 +384,9 @@ struct jpeg_compress_struct { UINT16 Y_density; /* Vertical pixel density */ boolean write_Adobe_marker; /* should an Adobe marker be written? */ + J_COLOR_TRANSFORM color_transform; + /* Color transform identifier, writes LSE marker if nonzero */ + /* State variable: index of next scanline to be written to * jpeg_write_scanlines(). Application may use this to control its * processing loop, e.g., "while (next_scanline < image_height)". @@ -379,19 +401,20 @@ struct jpeg_compress_struct { /* * These fields are computed during compression startup */ - int data_unit; /* size of data unit in samples */ - J_CODEC_PROCESS process; /* encoding process of JPEG image */ - + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to codec */ - /* The codec receives data in units of MCU rows as defined for fully - * interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * data_unit sample rows of each component in an + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an * "iMCU" (interleaved MCU) row. */ - + /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. @@ -399,16 +422,20 @@ struct jpeg_compress_struct { int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ - + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int data_units_in_MCU; /* # of data units per MCU */ - int MCU_membership[C_MAX_DATA_UNITS_IN_MCU]; + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ - int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for scan */ + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ /* * Links to compression subobjects (methods and private variables of modules) @@ -416,10 +443,12 @@ struct jpeg_compress_struct { struct jpeg_comp_master * master; struct jpeg_c_main_controller * main; struct jpeg_c_prep_controller * prep; - struct jpeg_c_codec * codec; + struct jpeg_c_coef_controller * coef; struct jpeg_marker_writer * marker; struct jpeg_color_converter * cconvert; struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ int script_space_size; }; @@ -554,6 +583,8 @@ struct jpeg_decompress_struct { jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ @@ -575,6 +606,9 @@ struct jpeg_decompress_struct { boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + J_COLOR_TRANSFORM color_transform; + /* Color transform identifier derived from LSE marker, otherwise zero */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ /* Aside from the specific data retained from APPn markers known to the @@ -590,21 +624,19 @@ struct jpeg_decompress_struct { /* * These fields are computed during decompression startup */ - int data_unit; /* size of data unit in samples */ - J_CODEC_PROCESS process; /* decoding process of JPEG image */ - int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ - int min_codec_data_unit; /* smallest codec_data_unit of any component */ + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The codec's input and output progress is measured in units of "iMCU" - * (interleaved MCU) rows. These are the same as MCU rows in fully - * interleaved JPEG scans, but are used whether the scan is interleaved - * or not. We define an iMCU row as v_samp_factor data_unit rows of each - * component. Therefore, the codec output contains - * v_samp_factor*codec_data_unit sample rows of a component per iMCU row. + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ @@ -621,12 +653,18 @@ struct jpeg_decompress_struct { JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - int data_units_in_MCU; /* # of data _units per MCU */ - int MCU_membership[D_MAX_DATA_UNITS_IN_MCU]; + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th data unit in an MCU */ + /* i'th block in an MCU */ - int Ss, Se, Ah, Al; /* progressive/lossless JPEG parms for scan */ + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ /* This field is shared between entropy decoder and marker parser. * It is either zero or the code of a JPEG marker that has been @@ -639,10 +677,12 @@ struct jpeg_decompress_struct { */ struct jpeg_decomp_master * master; struct jpeg_d_main_controller * main; - struct jpeg_d_codec * codec; + struct jpeg_d_coef_controller * coef; struct jpeg_d_post_controller * post; struct jpeg_input_controller * inputctl; struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; struct jpeg_upsampler * upsample; struct jpeg_color_deconverter * cconvert; struct jpeg_color_quantizer * cquantize; @@ -661,7 +701,7 @@ struct jpeg_decompress_struct { struct jpeg_error_mgr { /* Error exit handler: does not return to caller */ - JMETHOD(void, error_exit, (j_common_ptr cinfo)); + JMETHOD(noreturn_t, error_exit, (j_common_ptr cinfo)); /* Conditionally emit a trace or warning message */ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); /* Routine that actually outputs a trace or error message */ @@ -671,7 +711,7 @@ struct jpeg_error_mgr { #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ /* Reset error state variables at start of a new image */ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - + /* The message ID code and any parameters are saved here. * A message can have one string parameter or up to 8 int parameters. */ @@ -681,11 +721,11 @@ struct jpeg_error_mgr { int i[8]; char s[JMSG_STR_PARM_MAX]; } msg_parm; - + /* Standard state variables for error facility */ - + int trace_level; /* max msg_level that will be displayed */ - + /* For recoverable corrupt-data errors, we emit a warning message, * but keep going unless emit_message chooses to abort. emit_message * should count warnings in num_warnings. The surrounding application @@ -772,14 +812,6 @@ typedef struct jvirt_sarray_control * jvirt_sarray_ptr; typedef struct jvirt_barray_control * jvirt_barray_ptr; -#ifdef C_LOSSLESS_SUPPORTED -#define NEED_DARRAY -#else -#ifdef D_LOSSLESS_SUPPORTED -#define NEED_DARRAY -#endif -#endif - struct jpeg_memory_mgr { /* Method pointers */ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, @@ -792,11 +824,6 @@ struct jpeg_memory_mgr { JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows)); -#ifdef NEED_DARRAY - JMETHOD(JDIFFARRAY, alloc_darray, (j_common_ptr cinfo, int pool_id, - JDIMENSION diffsperrow, - JDIMENSION numrows)); -#endif JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, int pool_id, boolean pre_zero, @@ -856,7 +883,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); /* Short forms of external names for systems with brain-damaged linkers. * We shorten external names to be unique in the first six letters, which * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 + * (If your compiler itself needs names to be unique in less than 15 * characters, you are out of luck. Get a better compiler.) */ @@ -868,14 +895,16 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_destroy_decompress jDestDecompress #define jpeg_stdio_dest jStdDest #define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc #define jpeg_set_defaults jSetDefaults #define jpeg_set_colorspace jSetColorspace #define jpeg_default_colorspace jDefColorspace #define jpeg_set_quality jSetQuality #define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables #define jpeg_add_quant_table jAddQuantTable #define jpeg_quality_scaling jQualityScaling -#define jpeg_simple_lossless jSimLossless #define jpeg_simple_progression jSimProgress #define jpeg_suppress_tables jSuppressTables #define jpeg_alloc_quant_table jAlcQTable @@ -883,6 +912,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_start_compress jStrtCompress #define jpeg_write_scanlines jWrtScanlines #define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions #define jpeg_write_raw_data jWrtRawData #define jpeg_write_marker jWrtMarker #define jpeg_write_m_header jWrtMHeader @@ -899,6 +929,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_input_complete jInComplete #define jpeg_new_colormap jNewCMap #define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions #define jpeg_calc_output_dimensions jCalcDimensions #define jpeg_save_markers jSaveMarkers #define jpeg_set_marker_processor jSetMarker @@ -943,6 +974,14 @@ EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + const unsigned char * inbuffer, + unsigned long insize)); + /* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); /* Compression parameter setup aids */ @@ -954,13 +993,13 @@ EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, int scale_factor, boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline)); EXTERN(int) jpeg_quality_scaling JPP((int quality)); -EXTERN(void) jpeg_simple_lossless JPP((j_compress_ptr cinfo, - int predictor, int point_transform)); EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, boolean suppress)); @@ -975,12 +1014,15 @@ EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, JDIMENSION num_lines)); EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines)); -/* Write a special marker. See libjpeg.doc concerning safe usage. */ +/* Write a special marker. See libjpeg.txt concerning safe usage. */ EXTERN(void) jpeg_write_marker JPP((j_compress_ptr cinfo, int marker, const JOCTET * dataptr, unsigned int datalen)); @@ -1034,6 +1076,7 @@ EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); #define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ /* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); /* Control saving of COM and APPn markers into marker_list. */ @@ -1128,4 +1171,10 @@ struct jpeg_color_quantizer { long dummy; }; #include "jerror.h" /* fetch error codes too */ #endif +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + #endif /* JPEGLIB_H */ diff --git a/uppsrc/plugin/jpg/lib/jpegtran.c b/uppsrc/plugin/jpg/lib/jpegtran.c index 719aaa739..f3175aee2 100644 --- a/uppsrc/plugin/jpg/lib/jpegtran.c +++ b/uppsrc/plugin/jpg/lib/jpegtran.c @@ -1,14 +1,14 @@ /* * jpegtran.c * - * Copyright (C) 1995-1997, Thomas G. Lane. + * Copyright (C) 1995-2013, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a command-line user interface for JPEG transcoding. - * It is very similar to cjpeg.c, but provides lossless transcoding between - * different JPEG file formats. It also provides some lossless and sort-of- - * lossless transformations of JPEG data. + * It is very similar to cjpeg.c, and partly to djpeg.c, but provides + * lossless transcoding between different JPEG file formats. It also + * provides some lossless and sort-of-lossless transformations of JPEG data. */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ @@ -37,6 +37,7 @@ static const char * progname; /* program name for error messages */ static char * outfilename; /* for -outfile switch */ +static char * scaleoption; /* -scale switch */ static JCOPY_OPTION copyoption; /* -copy switch */ static jpeg_transform_info transformoption; /* image transformation options */ @@ -62,24 +63,30 @@ usage (void) #ifdef C_PROGRESSIVE_SUPPORTED fprintf(stderr, " -progressive Create progressive JPEG file\n"); #endif -#if TRANSFORMS_SUPPORTED fprintf(stderr, "Switches for modifying the image:\n"); - fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n"); +#if TRANSFORMS_SUPPORTED + fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular subarea\n"); fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n"); + fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n"); + fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n"); fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n"); +#endif + fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); +#if TRANSFORMS_SUPPORTED fprintf(stderr, " -transpose Transpose image\n"); fprintf(stderr, " -transverse Transverse transpose image\n"); fprintf(stderr, " -trim Drop non-transformable edge blocks\n"); -#endif /* TRANSFORMS_SUPPORTED */ + fprintf(stderr, " -wipe WxH+X+Y Wipe (gray out) a rectangular subarea\n"); +#endif fprintf(stderr, "Switches for advanced users:\n"); +#ifdef C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); fprintf(stderr, " -outfile name Specify name for output file\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, "Switches for wizards:\n"); -#ifdef C_ARITH_CODING_SUPPORTED - fprintf(stderr, " -arithmetic Use arithmetic coding\n"); -#endif #ifdef C_MULTISCAN_FILES_SUPPORTED fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n"); #endif @@ -130,10 +137,13 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, /* Set up default JPEG parameters. */ simple_progressive = FALSE; outfilename = NULL; + scaleoption = NULL; copyoption = JCOPYOPT_DEFAULT; transformoption.transform = JXFORM_NONE; + transformoption.perfect = FALSE; transformoption.trim = FALSE; transformoption.force_grayscale = FALSE; + transformoption.crop = FALSE; cinfo->err->trace_level = 0; /* Scan command line options, adjust parameters */ @@ -160,7 +170,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, exit(EXIT_FAILURE); #endif - } else if (keymatch(arg, "copy", 1)) { + } else if (keymatch(arg, "copy", 2)) { /* Select which extra markers to copy. */ if (++argn >= argc) /* advance to next argument */ usage(); @@ -173,6 +183,21 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, } else usage(); + } else if (keymatch(arg, "crop", 2)) { + /* Perform lossless cropping. */ +#if TRANSFORMS_SUPPORTED + if (++argn >= argc) /* advance to next argument */ + usage(); + if (transformoption.crop /* reject multiple crop/wipe requests */ || + ! jtransform_parse_crop_spec(&transformoption, argv[argn])) { + fprintf(stderr, "%s: bogus -crop argument '%s'\n", + progname, argv[argn]); + exit(EXIT_FAILURE); + } +#else + select_transform(JXFORM_NONE); /* force an error */ +#endif + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { /* Enable debug printouts. */ /* On first -d, print version identification */ @@ -233,7 +258,12 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, usage(); outfilename = argv[argn]; /* save it away for later use */ - } else if (keymatch(arg, "progressive", 1)) { + } else if (keymatch(arg, "perfect", 2)) { + /* Fail if there is any partial edge MCUs that the transform can't + * handle. */ + transformoption.perfect = TRUE; + + } else if (keymatch(arg, "progressive", 2)) { /* Select simple progressive mode. */ #ifdef C_PROGRESSIVE_SUPPORTED simple_progressive = TRUE; @@ -276,6 +306,13 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, else usage(); + } else if (keymatch(arg, "scale", 4)) { + /* Scale the output image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + scaleoption = argv[argn]; + /* We must postpone processing until decompression startup. */ + } else if (keymatch(arg, "scans", 1)) { /* Set scan script. */ #ifdef C_MULTISCAN_FILES_SUPPORTED @@ -301,6 +338,21 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, /* Trim off any partial edge MCUs that the transform can't handle. */ transformoption.trim = TRUE; + } else if (keymatch(arg, "wipe", 1)) { +#if TRANSFORMS_SUPPORTED + if (++argn >= argc) /* advance to next argument */ + usage(); + if (transformoption.crop /* reject multiple crop/wipe requests */ || + ! jtransform_parse_crop_spec(&transformoption, argv[argn])) { + fprintf(stderr, "%s: bogus -wipe argument '%s'\n", + progname, argv[argn]); + exit(EXIT_FAILURE); + } + select_transform(JXFORM_WIPE); +#else + select_transform(JXFORM_NONE); /* force an error */ +#endif + } else { usage(); /* bogus switch */ } @@ -342,8 +394,10 @@ main (int argc, char **argv) jvirt_barray_ptr * src_coef_arrays; jvirt_barray_ptr * dst_coef_arrays; int file_index; - FILE * input_file; - FILE * output_file; + /* We assume all-in-memory processing and can therefore use only a + * single file pointer for sequential input and output operation. + */ + FILE * fp; /* On Mac, fetch a command line. */ #ifdef USE_CCOMMAND @@ -406,24 +460,13 @@ main (int argc, char **argv) /* Open the input file. */ if (file_index < argc) { - if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); + if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ - input_file = read_stdin(); - } - - /* Open the output file. */ - if (outfilename != NULL) { - if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, outfilename); - exit(EXIT_FAILURE); - } - } else { - /* default output file is stdout */ - output_file = write_stdout(); + fp = read_stdin(); } #ifdef PROGRESS_REPORT @@ -431,7 +474,7 @@ main (int argc, char **argv) #endif /* Specify data source for decompression */ - jpeg_stdio_src(&srcinfo, input_file); + jpeg_stdio_src(&srcinfo, fp); /* Enable saving of extra markers that we want to copy */ jcopy_markers_setup(&srcinfo, copyoption); @@ -439,11 +482,22 @@ main (int argc, char **argv) /* Read file header */ (void) jpeg_read_header(&srcinfo, TRUE); + /* Adjust default decompression parameters */ + if (scaleoption != NULL) + if (sscanf(scaleoption, "%u/%u", + &srcinfo.scale_num, &srcinfo.scale_denom) < 1) + usage(); + /* Any space needed by a transform option must be requested before * jpeg_read_coefficients so that memory allocation will be done right. */ #if TRANSFORMS_SUPPORTED - jtransform_request_workspace(&srcinfo, &transformoption); + /* Fail right away if -perfect is given and transformation is not perfect. + */ + if (!jtransform_request_workspace(&srcinfo, &transformoption)) { + fprintf(stderr, "%s: transformation is not perfect\n", progname); + exit(EXIT_FAILURE); + } #endif /* Read source file as DCT coefficients */ @@ -463,11 +517,32 @@ main (int argc, char **argv) dst_coef_arrays = src_coef_arrays; #endif + /* Close input file, if we opened it. + * Note: we assume that jpeg_read_coefficients consumed all input + * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will + * only consume more while (! cinfo->inputctl->eoi_reached). + * We cannot call jpeg_finish_decompress here since we still need the + * virtual arrays allocated from the source object for processing. + */ + if (fp != stdin) + fclose(fp); + + /* Open the output file. */ + if (outfilename != NULL) { + if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ + fp = write_stdout(); + } + /* Adjust default compression parameters by re-parsing the options */ file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE); /* Specify data destination for compression */ - jpeg_stdio_dest(&dstinfo, output_file); + jpeg_stdio_dest(&dstinfo, fp); /* Start compressor (note no image data is actually written here) */ jpeg_write_coefficients(&dstinfo, dst_coef_arrays); @@ -488,11 +563,9 @@ main (int argc, char **argv) (void) jpeg_finish_decompress(&srcinfo); jpeg_destroy_decompress(&srcinfo); - /* Close files, if we opened them */ - if (input_file != stdin) - fclose(input_file); - if (output_file != stdout) - fclose(output_file); + /* Close output file, if we opened it */ + if (fp != stdout) + fclose(fp); #ifdef PROGRESS_REPORT end_progress_monitor((j_common_ptr) &dstinfo); diff --git a/uppsrc/plugin/jpg/lib/jquant1.c b/uppsrc/plugin/jpg/lib/jquant1.c index a64baacbc..1c482bc4b 100644 --- a/uppsrc/plugin/jpg/lib/jquant1.c +++ b/uppsrc/plugin/jpg/lib/jquant1.c @@ -2,6 +2,7 @@ * jquant1.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2011 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -424,7 +425,7 @@ make_odither_array (j_decompress_ptr cinfo, int ncolors) /* * Create the ordered-dither tables. - * Components having the same number of representative colors may + * Components having the same number of representative colors may * share a dither table. */ @@ -530,8 +531,8 @@ quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ - jzero_far((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); + FMEMZERO((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); row_index = cquantize->row_index; for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; @@ -635,8 +636,8 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ - jzero_far((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); + FMEMZERO((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; @@ -781,7 +782,7 @@ start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) /* Initialize the propagated errors to zero. */ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); for (i = 0; i < cinfo->out_color_components; i++) - jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + FMEMZERO((void FAR *) cquantize->fserrors[i], arraysize); break; default: ERREXIT(cinfo, JERR_NOT_COMPILED); diff --git a/uppsrc/plugin/jpg/lib/jquant2.c b/uppsrc/plugin/jpg/lib/jquant2.c index 7afd9b32d..f7e351f2a 100644 --- a/uppsrc/plugin/jpg/lib/jquant2.c +++ b/uppsrc/plugin/jpg/lib/jquant2.c @@ -2,6 +2,7 @@ * jquant2.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2011 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -41,7 +42,7 @@ * color space, and repeatedly splits the "largest" remaining box until we * have as many boxes as desired colors. Then the mean color in each * remaining box becomes one of the possible output colors. - * + * * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires @@ -278,7 +279,7 @@ find_biggest_color_pop (boxptr boxlist, int numboxes) register int i; register long maxc = 0; boxptr which = NULL; - + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->colorcount > maxc && boxp->volume > 0) { which = boxp; @@ -298,7 +299,7 @@ find_biggest_volume (boxptr boxlist, int numboxes) register int i; register INT32 maxv = 0; boxptr which = NULL; - + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->volume > maxv) { which = boxp; @@ -321,11 +322,11 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) int c0min,c0max,c1min,c1max,c2min,c2max; INT32 dist0,dist1,dist2; long ccount; - + c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; - + if (c0max > c0min) for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { @@ -405,7 +406,7 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; - + /* Now scan remaining volume of box and compute population */ ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) @@ -511,11 +512,11 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) long c0total = 0; long c1total = 0; long c2total = 0; - + c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; - + for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; @@ -528,7 +529,7 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) } } } - + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); @@ -797,17 +798,17 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, bptr = bestdist; for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) *bptr++ = 0x7FFFFFFFL; - + /* For each color selected by find_nearby_colors, * compute its distance to the center of each cell in the box. * If that's less than best-so-far, update best distance and color number. */ - + /* Nominal steps between cell centers ("x" in Thomas article) */ #define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) #define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) #define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) - + for (i = 0; i < numcolors; i++) { icolor = GETJSAMPLE(colorlist[i]); /* Compute (square of) distance from minc0/c1/c2 to this color */ @@ -881,7 +882,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); - + /* Determine which colormap entries are close enough to be candidates * for the nearest entry to some cell in the update box. */ @@ -1203,7 +1204,7 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); /* Initialize the propagated errors to zero. */ - jzero_far((void FAR *) cquantize->fserrors, arraysize); + FMEMZERO((void FAR *) cquantize->fserrors, arraysize); /* Make the error-limit table if we didn't already. */ if (cquantize->error_limiter == NULL) init_error_limit(cinfo); @@ -1214,8 +1215,8 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) /* Zero the histogram or inverse color map, if necessary */ if (cquantize->needs_zeroed) { for (i = 0; i < HIST_C0_ELEMS; i++) { - jzero_far((void FAR *) histogram[i], - HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + FMEMZERO((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); } cquantize->needs_zeroed = FALSE; } diff --git a/uppsrc/plugin/jpg/lib/jutils.c b/uppsrc/plugin/jpg/lib/jutils.c index 286cda207..037a79529 100644 --- a/uppsrc/plugin/jpg/lib/jutils.c +++ b/uppsrc/plugin/jpg/lib/jutils.c @@ -2,6 +2,7 @@ * jutils.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2009-2011 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -63,6 +64,57 @@ const int jpeg_natural_order[DCTSIZE2+16] = { 63, 63, 63, 63, 63, 63, 63, 63 }; +const int jpeg_natural_order7[7*7+16] = { + 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, 14, 21, 28, 35, + 42, 49, 50, 43, 36, 29, 22, 30, + 37, 44, 51, 52, 45, 38, 46, 53, + 54, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order6[6*6+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 41, 34, 27, + 20, 13, 21, 28, 35, 42, 43, 36, + 29, 37, 44, 45, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order5[5*5+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 12, + 19, 26, 33, 34, 27, 20, 28, 35, + 36, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order4[4*4+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 25, 18, 11, 19, 26, 27, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order3[3*3+16] = { + 0, 1, 8, 16, 9, 2, 10, 17, + 18, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order2[2*2+16] = { + 0, 1, 8, 9, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + /* * Arithmetic utilities @@ -96,13 +148,27 @@ jround_up (long a, long b) * is not all that great, because these routines aren't very heavily used.) */ -#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */ #define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) -#define FMEMZERO(target,size) MEMZERO(target,size) #else /* 80x86 case, define if we can */ #ifdef USE_FMEM #define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) -#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#else +/* This function is for use by the FMEMZERO macro defined in jpegint.h. + * Do not call this function directly, use the FMEMZERO macro instead. + */ +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +} #endif #endif @@ -159,21 +225,3 @@ jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, } #endif } - - -GLOBAL(void) -jzero_far (void FAR * target, size_t bytestozero) -/* Zero out a chunk of FAR memory. */ -/* This might be sample-array data, block-array data, or alloc_large data. */ -{ -#ifdef FMEMZERO - FMEMZERO(target, bytestozero); -#else - register char FAR * ptr = (char FAR *) target; - register size_t count; - - for (count = bytestozero; count > 0; count--) { - *ptr++ = 0; - } -#endif -} diff --git a/uppsrc/plugin/jpg/lib/jversion.h b/uppsrc/plugin/jpg/lib/jversion.h index dadd453a4..bb53ffe71 100644 --- a/uppsrc/plugin/jpg/lib/jversion.h +++ b/uppsrc/plugin/jpg/lib/jversion.h @@ -1,7 +1,7 @@ /* * jversion.h * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -9,6 +9,6 @@ */ -#define JVERSION "6b 27-Mar-1998" +#define JVERSION "9b 17-Jan-2016" -#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" +#define JCOPYRIGHT "Copyright (C) 2016, Thomas G. Lane, Guido Vollbeding" diff --git a/uppsrc/plugin/jpg/lib/rdbmp.c b/uppsrc/plugin/jpg/lib/rdbmp.c index 4f61bcf73..dfdf96ff5 100644 --- a/uppsrc/plugin/jpg/lib/rdbmp.c +++ b/uppsrc/plugin/jpg/lib/rdbmp.c @@ -2,6 +2,7 @@ * rdbmp.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -177,10 +178,41 @@ get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) } +METHODDEF(JDIMENSION) +get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 32-bit pixels */ +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source->source_row, (JDIMENSION) 1, FALSE); + /* Transfer data. Note source values are in BGR order + * (even though Microsoft's own documents say the opposite). + */ + inptr = image_ptr[0]; + outptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[1] = *inptr++; + outptr[0] = *inptr++; + inptr++; /* skip the 4th byte (Alpha channel) */ + outptr += 3; + } + + return 1; +} + + /* * This method loads the image into whole_image during the first call on * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call - * get_8bit_row or get_24bit_row on subsequent calls. + * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls. */ METHODDEF(JDIMENSION) @@ -223,6 +255,9 @@ preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) case 24: source->pub.get_pixel_rows = get_24bit_row; break; + case 32: + source->pub.get_pixel_rows = get_32bit_row; + break; default: ERREXIT(cinfo, JERR_BMP_BADDEPTH); } @@ -251,8 +286,8 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) (((INT32) UCH(array[offset+3])) << 24)) INT32 bfOffBits; INT32 headerSize; - INT32 biWidth = 0; /* initialize to avoid compiler warning */ - INT32 biHeight = 0; + INT32 biWidth; + INT32 biHeight; unsigned int biPlanes; INT32 biCompression; INT32 biXPelsPerMeter,biYPelsPerMeter; @@ -300,8 +335,6 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) ERREXIT(cinfo, JERR_BMP_BADDEPTH); break; } - if (biPlanes != 1) - ERREXIT(cinfo, JERR_BMP_BADPLANES); break; case 40: case 64: @@ -325,12 +358,13 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) case 24: /* RGB image */ TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); break; + case 32: /* RGB image + Alpha channel */ + TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); + break; default: ERREXIT(cinfo, JERR_BMP_BADDEPTH); break; } - if (biPlanes != 1) - ERREXIT(cinfo, JERR_BMP_BADPLANES); if (biCompression != 0) ERREXIT(cinfo, JERR_BMP_COMPRESSED); @@ -343,9 +377,14 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) break; default: ERREXIT(cinfo, JERR_BMP_BADHEADER); - break; + return; } + if (biWidth <= 0 || biHeight <= 0) + ERREXIT(cinfo, JERR_BMP_EMPTY); + if (biPlanes != 1) + ERREXIT(cinfo, JERR_BMP_BADPLANES); + /* Compute distance to bitmap data --- will adjust for colormap below */ bPad = bfOffBits - (headerSize + 14); @@ -375,6 +414,8 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* Compute row width in file, including padding to 4-byte boundary */ if (source->bits_per_pixel == 24) row_width = (JDIMENSION) (biWidth * 3); + else if (source->bits_per_pixel == 32) + row_width = (JDIMENSION) (biWidth * 4); else row_width = (JDIMENSION) biWidth; while ((row_width & 3) != 0) row_width++; diff --git a/uppsrc/plugin/jpg/lib/rdcolmap.c b/uppsrc/plugin/jpg/lib/rdcolmap.c index 0cf5cc24d..eebf8346c 100644 --- a/uppsrc/plugin/jpg/lib/rdcolmap.c +++ b/uppsrc/plugin/jpg/lib/rdcolmap.c @@ -123,7 +123,7 @@ pbm_getc (FILE * infile) /* A comment/newline sequence is returned as a newline */ { register int ch; - + ch = getc(infile); if (ch == '#') { do { @@ -143,17 +143,17 @@ read_pbm_integer (j_decompress_ptr cinfo, FILE * infile) { register int ch; register unsigned int val; - + /* Skip any leading whitespace */ do { ch = pbm_getc(infile); if (ch == EOF) ERREXIT(cinfo, JERR_BAD_CMAP_FILE); } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); - + if (ch < '0' || ch > '9') ERREXIT(cinfo, JERR_BAD_CMAP_FILE); - + val = ch - '0'; while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { val *= 10; diff --git a/uppsrc/plugin/jpg/lib/rdjpgcom.c b/uppsrc/plugin/jpg/lib/rdjpgcom.c index c8b94bb8a..ab09b443f 100644 --- a/uppsrc/plugin/jpg/lib/rdjpgcom.c +++ b/uppsrc/plugin/jpg/lib/rdjpgcom.c @@ -2,6 +2,7 @@ * rdjpgcom.c * * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2009 by Bill Allombert, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -14,6 +15,9 @@ #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ #include "jinclude.h" /* get auto-config symbols, */ +#ifdef HAVE_LOCALE_H +#include /* Bill Allombert: use locale for isprint */ +#endif #include /* to declare isupper(), tolower() */ #ifdef USE_SETMODE #include /* to declare setmode()'s parameter macros */ @@ -218,12 +222,17 @@ skip_variable (void) */ static void -process_COM (void) +process_COM (int raw) { unsigned int length; int ch; int lastch = 0; + /* Bill Allombert: set locale properly for isprint */ +#ifdef HAVE_LOCALE_H + setlocale(LC_CTYPE, ""); +#endif + /* Get the marker parameter length count */ length = read_2_bytes(); /* Length includes itself, so must be at least 2 */ @@ -233,12 +242,14 @@ process_COM (void) while (length > 0) { ch = read_1_byte(); + if (raw) { + putc(ch, stdout); /* Emit the character in a readable form. * Nonprintables are converted to \nnn form, * while \ is converted to \\. * Newlines in CR, CR/LF, or LF form will be printed as one newline. */ - if (ch == '\r') { + } else if (ch == '\r') { printf("\n"); } else if (ch == '\n') { if (lastch != '\r') @@ -254,6 +265,11 @@ process_COM (void) length--; } printf("\n"); + + /* Bill Allombert: revert to C locale */ +#ifdef HAVE_LOCALE_H + setlocale(LC_CTYPE, "C"); +#endif } @@ -321,7 +337,7 @@ process_SOFn (int marker) */ static int -scan_JPEG_header (int verbose) +scan_JPEG_header (int verbose, int raw) { int marker; @@ -362,7 +378,7 @@ scan_JPEG_header (int verbose) return marker; case M_COM: - process_COM(); + process_COM(raw); break; case M_APP12: @@ -371,7 +387,7 @@ scan_JPEG_header (int verbose) */ if (verbose) { printf("APP12 contains:\n"); - process_COM(); + process_COM(raw); } else skip_variable(); break; @@ -398,6 +414,7 @@ usage (void) fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -raw Display non-printable characters in comments (unsafe)\n"); fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); exit(EXIT_FAILURE); @@ -438,7 +455,7 @@ main (int argc, char **argv) { int argn; char * arg; - int verbose = 0; + int verbose = 0, raw = 0; /* On Mac, fetch a command line. */ #ifdef USE_CCOMMAND @@ -457,6 +474,8 @@ main (int argc, char **argv) arg++; /* advance over '-' */ if (keymatch(arg, "verbose", 1)) { verbose++; + } else if (keymatch(arg, "raw", 1)) { + raw = 1; } else usage(); } @@ -488,7 +507,7 @@ main (int argc, char **argv) } /* Scan the JPEG headers. */ - (void) scan_JPEG_header(verbose); + (void) scan_JPEG_header(verbose, raw); /* All done. */ exit(EXIT_SUCCESS); diff --git a/uppsrc/plugin/jpg/lib/rdppm.c b/uppsrc/plugin/jpg/lib/rdppm.c index bec0bc06d..9dcd2dc21 100644 --- a/uppsrc/plugin/jpg/lib/rdppm.c +++ b/uppsrc/plugin/jpg/lib/rdppm.c @@ -2,6 +2,7 @@ * rdppm.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2009 by Bill Allombert, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -250,8 +251,8 @@ get_word_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) bufferptr = source->iobuffer; for (col = cinfo->image_width; col > 0; col--) { register int temp; - temp = UCH(*bufferptr++); - temp |= UCH(*bufferptr++) << 8; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); *ptr++ = rescale[temp]; } return 1; @@ -274,14 +275,14 @@ get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) bufferptr = source->iobuffer; for (col = cinfo->image_width; col > 0; col--) { register int temp; - temp = UCH(*bufferptr++); - temp |= UCH(*bufferptr++) << 8; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); *ptr++ = rescale[temp]; - temp = UCH(*bufferptr++); - temp |= UCH(*bufferptr++) << 8; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); *ptr++ = rescale[temp]; - temp = UCH(*bufferptr++); - temp |= UCH(*bufferptr++) << 8; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); *ptr++ = rescale[temp]; } return 1; diff --git a/uppsrc/plugin/jpg/lib/rdrle.c b/uppsrc/plugin/jpg/lib/rdrle.c index 154d937a8..df871e00a 100644 --- a/uppsrc/plugin/jpg/lib/rdrle.c +++ b/uppsrc/plugin/jpg/lib/rdrle.c @@ -38,7 +38,7 @@ /* * We support the following types of RLE files: - * + * * GRAYSCALE - 8 bits, no colormap * MAPPEDGRAY - 8 bits, 1 channel colomap * PSEUDOCOLOR - 8 bits, 3 channel colormap @@ -111,7 +111,7 @@ start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) } /* Figure out what we have, set private vars and return values accordingly */ - + width = source->header.xmax - source->header.xmin + 1; height = source->header.ymax - source->header.ymin + 1; source->header.xmin = 0; /* realign horizontally */ @@ -141,7 +141,7 @@ start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) TRACEMS2(cinfo, 1, JTRC_RLE, width, height); } else ERREXIT(cinfo, JERR_RLE_UNSUPPORTED); - + if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) { cinfo->in_color_space = JCS_GRAYSCALE; cinfo->input_components = 1; @@ -348,7 +348,7 @@ load_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) source->row = cinfo->image_height; /* And fetch the topmost (bottommost) row */ - return (*source->pub.get_pixel_rows) (cinfo, sinfo); + return (*source->pub.get_pixel_rows) (cinfo, sinfo); } diff --git a/uppsrc/plugin/jpg/lib/rdswitch.c b/uppsrc/plugin/jpg/lib/rdswitch.c index d91c5fdc6..05753a302 100644 --- a/uppsrc/plugin/jpg/lib/rdswitch.c +++ b/uppsrc/plugin/jpg/lib/rdswitch.c @@ -2,6 +2,7 @@ * rdswitch.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2003-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -9,6 +10,7 @@ * command-line switches. Switches processed here are: * -qtables file Read quantization tables from text file * -scans file Read scan script from text file + * -quality N[,N,...] Set quality ratings * -qslots N[,N,...] Set component quantization table selectors * -sample HxV[,HxV,...] Set component sampling factors */ @@ -23,7 +25,7 @@ text_getc (FILE * file) /* A comment/newline sequence is returned as a newline */ { register int ch; - + ch = getc(file); if (ch == '#') { do { @@ -41,7 +43,7 @@ read_text_integer (FILE * file, long * result, int * termchar) { register int ch; register long val; - + /* Skip any leading whitespace, detect EOF */ do { ch = text_getc(file); @@ -50,7 +52,7 @@ read_text_integer (FILE * file, long * result, int * termchar) return FALSE; } } while (isspace(ch)); - + if (! isdigit(ch)) { *termchar = ch; return FALSE; @@ -70,8 +72,7 @@ read_text_integer (FILE * file, long * result, int * termchar) GLOBAL(boolean) -read_quant_tables (j_compress_ptr cinfo, char * filename, - int scale_factor, boolean force_baseline) +read_quant_tables (j_compress_ptr cinfo, char * filename, boolean force_baseline) /* Read a set of quantization tables from the specified file. * The file is plain ASCII text: decimal numbers with whitespace between. * Comments preceded by '#' may be included in the file. @@ -108,7 +109,8 @@ read_quant_tables (j_compress_ptr cinfo, char * filename, } table[i] = (unsigned int) val; } - jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno], + force_baseline); tblno++; } @@ -262,6 +264,38 @@ bogus: #endif /* C_MULTISCAN_FILES_SUPPORTED */ +GLOBAL(boolean) +set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline) +/* Process a quality-ratings parameter string, of the form + * N[,N,...] + * If there are more q-table slots than parameters, the last value is replicated. + */ +{ + int val = 75; /* default value */ + int tblno; + char ch; + + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (*arg) { + ch = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c", &val, &ch) < 1) + return FALSE; + if (ch != ',') /* syntax check */ + return FALSE; + /* Convert user 0-100 rating to percentage scaling */ + cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); + while (*arg && *arg++ != ',') /* advance to next segment of arg string */ + ; + } else { + /* reached end of parameter, set remaining factors to last value */ + cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); + } + } + jpeg_default_qtables(cinfo, force_baseline); + return TRUE; +} + + GLOBAL(boolean) set_quant_slots (j_compress_ptr cinfo, char *arg) /* Process a quantization-table-selectors parameter string, of the form @@ -314,8 +348,9 @@ set_sample_factors (j_compress_ptr cinfo, char *arg) return FALSE; if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */ return FALSE; - if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) { - fprintf(stderr, "JPEG sampling factors must be 1..4\n"); + if (val1 <= 0 || val1 > MAX_SAMP_FACTOR || + val2 <= 0 || val2 > MAX_SAMP_FACTOR) { + fprintf(stderr, "JPEG sampling factors must be 1..%d\n", MAX_SAMP_FACTOR); return FALSE; } cinfo->comp_info[ci].h_samp_factor = val1; @@ -330,29 +365,3 @@ set_sample_factors (j_compress_ptr cinfo, char *arg) } return TRUE; } - - -#ifdef C_LOSSLESS_SUPPORTED - -GLOBAL(boolean) -set_simple_lossless (j_compress_ptr cinfo, char *arg) -{ - int pred, pt = 0; - char ch; - - ch = ','; /* if not set by sscanf, will be ',' */ - if (sscanf(arg, "%d%c", &pred, &ch) < 1) - return FALSE; - if (ch != ',') /* syntax check */ - return FALSE; - while (*arg && *arg++ != ',') /* advance to next segment of arg string */ - ; - if (*arg) { - if (sscanf(arg, "%d", &pt) != 1) - pt = 0; - } - jpeg_simple_lossless(cinfo, pred, pt); - return TRUE; -} - -#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/rdtarga.c b/uppsrc/plugin/jpg/lib/rdtarga.c index b99b829de..d7ffc33eb 100644 --- a/uppsrc/plugin/jpg/lib/rdtarga.c +++ b/uppsrc/plugin/jpg/lib/rdtarga.c @@ -177,7 +177,7 @@ get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) tga_source_ptr source = (tga_source_ptr) sinfo; register JSAMPROW ptr; register JDIMENSION col; - + ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ @@ -215,7 +215,7 @@ get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) register int t; register JSAMPROW ptr; register JDIMENSION col; - + ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ @@ -242,7 +242,7 @@ get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) tga_source_ptr source = (tga_source_ptr) sinfo; register JSAMPROW ptr; register JDIMENSION col; - + ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ @@ -365,7 +365,7 @@ start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */ interlace_type != 0) /* currently don't allow interlaced image */ ERREXIT(cinfo, JERR_TGA_BADPARMS); - + if (subtype > 8) { /* It's an RLE-coded file */ source->read_pixel = read_rle_pixel; @@ -440,7 +440,7 @@ start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) source->pub.buffer_height = 1; source->pub.get_pixel_rows = source->get_pixel_rows; } - + while (idlen--) /* Throw away ID field */ (void) read_byte(source); diff --git a/uppsrc/plugin/jpg/lib/transupp.c b/uppsrc/plugin/jpg/lib/transupp.c index e2e9d521b..0524d1fc2 100644 --- a/uppsrc/plugin/jpg/lib/transupp.c +++ b/uppsrc/plugin/jpg/lib/transupp.c @@ -1,7 +1,7 @@ /* * transupp.c * - * Copyright (C) 1997-1998, Thomas G. Lane. + * Copyright (C) 1997-2013, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -20,6 +20,7 @@ #include "jinclude.h" #include "jpeglib.h" #include "transupp.h" /* My own external interface */ +#include /* to declare isdigit() */ #if TRANSFORMS_SUPPORTED @@ -28,7 +29,8 @@ * Lossless image transformation routines. These routines work on DCT * coefficient arrays and thus do not require any lossy decompression * or recompression of the image. - * Thanks to Guido Vollbeding for the initial design and code of this feature. + * Thanks to Guido Vollbeding for the initial design and code of this feature, + * and to Ben Jackson for introducing the cropping feature. * * Horizontal flipping is done in-place, using a single top-to-bottom * pass through the virtual source array. It will thus be much the @@ -42,6 +44,13 @@ * arrays for most of the transforms. That could result in much thrashing * if the image is larger than main memory. * + * If cropping or trimming is involved, the destination arrays may be smaller + * than the source arrays. Note it is not possible to do horizontal flip + * in-place when a nonzero Y crop offset is specified, since we'd have to move + * data from one block row to another but the virtual array manager doesn't + * guarantee we can touch more than one row at a time. So in that case, + * we have to use a separate destination array. + * * Some notes about the operating environment of the individual transform * routines: * 1. Both the source and destination virtual arrays are allocated from the @@ -54,20 +63,175 @@ * and we may as well take that as the effective iMCU size. * 4. When "trim" is in effect, the destination's dimensions will be the * trimmed values but the source's will be untrimmed. - * 5. All the routines assume that the source and destination buffers are + * 5. When "crop" is in effect, the destination's dimensions will be the + * cropped values but the source's will be uncropped. Each transform + * routine is responsible for picking up source data starting at the + * correct X and Y offset for the crop region. (The X and Y offsets + * passed to the transform routines are measured in iMCU blocks of the + * destination.) + * 6. All the routines assume that the source and destination buffers are * padded out to a full iMCU boundary. This is true, although for the * source buffer it is an undocumented property of jdcoefct.c. - * Notes 2,3,4 boil down to this: generally we should use the destination's - * dimensions and ignore the source's. */ LOCAL(void) -do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays) -/* Horizontal flip; done in-place, so no separate dest array is required */ +do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Crop. This is only used when no rotate/flip is requested with the crop. */ { - JDIMENSION MCU_cols, comp_width, blk_x, blk_y; + JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + jpeg_component_info *compptr; + + /* We simply have to copy the right amount of data (the destination's + * image size) starting at the given X and Y offsets in the source. + */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], + compptr->width_in_blocks); + } + } + } +} + + +LOCAL(void) +do_crop_ext (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Crop. This is only used when no rotate/flip is requested with the crop. + * Extension: If the destination size is larger than the source, we fill in + * the extra area with zero (neutral gray). Note we also have to zero partial + * iMCUs at the right and bottom edge of the source image area in this case. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; + JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + jpeg_component_info *compptr; + + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + if (dstinfo->jpeg_height > srcinfo->output_height) { + if (dst_blk_y < y_crop_blocks || + dst_blk_y >= comp_height + y_crop_blocks) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + FMEMZERO(dst_buffer[offset_y], + compptr->width_in_blocks * SIZEOF(JBLOCK)); + } + continue; + } + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y - y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } else { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (dstinfo->jpeg_width > srcinfo->output_width) { + if (x_crop_blocks > 0) { + FMEMZERO(dst_buffer[offset_y], + x_crop_blocks * SIZEOF(JBLOCK)); + } + jcopy_block_row(src_buffer[offset_y], + dst_buffer[offset_y] + x_crop_blocks, + comp_width); + if (compptr->width_in_blocks > comp_width + x_crop_blocks) { + FMEMZERO(dst_buffer[offset_y] + + comp_width + x_crop_blocks, + (compptr->width_in_blocks - + comp_width - x_crop_blocks) * SIZEOF(JBLOCK)); + } + } else { + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], + compptr->width_in_blocks); + } + } + } + } +} + + +LOCAL(void) +do_wipe (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + JDIMENSION drop_width, JDIMENSION drop_height) +/* Wipe - drop content of specified area, fill with zero (neutral gray) */ +{ + JDIMENSION comp_width, comp_height; + JDIMENSION blk_y, x_wipe_blocks, y_wipe_blocks; + int ci, offset_y; + JBLOCKARRAY buffer; + jpeg_component_info *compptr; + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = drop_width * compptr->h_samp_factor; + comp_height = drop_height * compptr->v_samp_factor; + x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; + y_wipe_blocks = y_crop_offset * compptr->v_samp_factor; + for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) { + buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y + y_wipe_blocks, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + FMEMZERO(buffer[offset_y] + x_wipe_blocks, + comp_width * SIZEOF(JBLOCK)); + } + } + } +} + + +LOCAL(void) +do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, + jvirt_barray_ptr *src_coef_arrays) +/* Horizontal flip; done in-place, so no separate dest array is required. + * NB: this only works when y_crop_offset is zero. + */ +{ + JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; int ci, k, offset_y; JBLOCKARRAY buffer; JCOEFPTR ptr1, ptr2; @@ -79,17 +243,20 @@ do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * mirroring by changing the signs of odd-numbered columns. * Partial iMCUs at the right edge are left untouched. */ - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_width = MCU_cols * compptr->h_samp_factor; - for (blk_y = 0; blk_y < compptr->height_in_data_units; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + for (blk_y = 0; blk_y < compptr->height_in_blocks; blk_y += compptr->v_samp_factor) { buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + /* Do the mirroring */ for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { ptr1 = buffer[offset_y][blk_x]; ptr2 = buffer[offset_y][comp_width - blk_x - 1]; @@ -105,6 +272,80 @@ do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, *ptr2++ = -temp1; } } + if (x_crop_blocks > 0) { + /* Now left-justify the portion of the data to be kept. + * We can't use a single jcopy_block_row() call because that routine + * depends on memcpy(), whose behavior is unspecified for overlapping + * source and destination areas. Sigh. + */ + for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { + jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, + buffer[offset_y] + blk_x, + (JDIMENSION) 1); + } + } + } + } + } +} + + +LOCAL(void) +do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Horizontal flip in general cropping case */ +{ + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, k, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Here we must output into a separate array because we can't touch + * different rows of a single virtual array simultaneously. Otherwise, + * this is essentially the same as the routine above. + */ + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[offset_y]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Do the mirrorable blocks */ + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + *dst_ptr++ = *src_ptr++; /* copy even column */ + *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ + } + } else { + /* Copy last partial block(s) verbatim */ + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, + dst_row_ptr + dst_blk_x, + (JDIMENSION) 1); + } + } } } } @@ -113,11 +354,13 @@ do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, LOCAL(void) do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) /* Vertical flip */ { JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; int ci, i, j, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JBLOCKROW src_row_ptr, dst_row_ptr; @@ -131,34 +374,40 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * of odd-numbered rows. * Partial iMCUs at the bottom edge are copied verbatim. */ - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_height = MCU_rows * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - if (dst_blk_y < comp_height) { + if (y_crop_blocks + dst_blk_y < comp_height) { /* Row is within the mirrorable area. */ src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], - comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, + comp_height - y_crop_blocks - dst_blk_y - + (JDIMENSION) compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } else { /* Bottom-edge blocks will be copied verbatim. */ src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, (JDIMENSION) compptr->v_samp_factor, FALSE); } for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - if (dst_blk_y < comp_height) { + if (y_crop_blocks + dst_blk_y < comp_height) { /* Row is within the mirrorable area. */ dst_row_ptr = dst_buffer[offset_y]; src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units; + src_row_ptr += x_crop_blocks; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { dst_ptr = dst_row_ptr[dst_blk_x]; src_ptr = src_row_ptr[dst_blk_x]; @@ -173,8 +422,9 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, } } else { /* Just copy row verbatim. */ - jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y], - compptr->width_in_data_units); + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], + compptr->width_in_blocks); } } } @@ -184,11 +434,12 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, LOCAL(void) do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) /* Transpose source into destination */ { - JDIMENSION dst_blk_x, dst_blk_y; + JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; int ci, i, j, offset_x, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JCOEFPTR src_ptr, dst_ptr; @@ -201,20 +452,23 @@ do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, */ for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) { src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, (JDIMENSION) compptr->h_samp_factor, FALSE); for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -228,6 +482,7 @@ do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, LOCAL(void) do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) /* 90 degree rotation is equivalent to @@ -237,6 +492,7 @@ do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, */ { JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; int ci, i, j, offset_x, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JCOEFPTR src_ptr, dst_ptr; @@ -246,28 +502,42 @@ do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * at the (output) right edge properly. They just get transposed and * not mirrored. */ - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_height / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_width = MCU_cols * compptr->h_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) { - src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, - (JDIMENSION) compptr->h_samp_factor, FALSE); + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_width - x_crop_blocks - dst_blk_x - + (JDIMENSION) compptr->h_samp_factor, + (JDIMENSION) compptr->h_samp_factor, FALSE); + } else { + /* Edge blocks are transposed but not mirrored. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION) compptr->h_samp_factor, FALSE); + } for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; - if (dst_blk_x < comp_width) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (x_crop_blocks + dst_blk_x < comp_width) { /* Block is within the mirrorable area. */ - dst_ptr = dst_buffer[offset_y] - [comp_width - dst_blk_x - offset_x - 1]; + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [dst_blk_y + offset_y + y_crop_blocks]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -277,7 +547,8 @@ do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, } } else { /* Edge blocks are transposed but not mirrored. */ - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -292,6 +563,7 @@ do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, LOCAL(void) do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) /* 270 degree rotation is equivalent to @@ -301,6 +573,7 @@ do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, */ { JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; int ci, i, j, offset_x, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JCOEFPTR src_ptr, dst_ptr; @@ -310,28 +583,32 @@ do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * at the (output) bottom edge properly. They just get transposed and * not mirrored. */ - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_height = MCU_rows * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) { src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, (JDIMENSION) compptr->h_samp_factor, FALSE); for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; - if (dst_blk_y < comp_height) { + if (y_crop_blocks + dst_blk_y < comp_height) { /* Block is within the mirrorable area. */ src_ptr = src_buffer[offset_x] - [comp_height - dst_blk_y - offset_y - 1]; + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) { dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -341,7 +618,8 @@ do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, } } else { /* Edge blocks are transposed but not mirrored. */ - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -356,6 +634,7 @@ do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, LOCAL(void) do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) /* 180 degree rotation is equivalent to @@ -365,89 +644,95 @@ do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, */ { JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; int ci, i, j, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JBLOCKROW src_row_ptr, dst_row_ptr; JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_width = MCU_cols * compptr->h_samp_factor; comp_height = MCU_rows * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - if (dst_blk_y < comp_height) { + if (y_crop_blocks + dst_blk_y < comp_height) { /* Row is within the vertically mirrorable area. */ src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], - comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, + comp_height - y_crop_blocks - dst_blk_y - + (JDIMENSION) compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } else { /* Bottom-edge rows are only mirrored horizontally. */ src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, (JDIMENSION) compptr->v_samp_factor, FALSE); } for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - if (dst_blk_y < comp_height) { + dst_row_ptr = dst_buffer[offset_y]; + if (y_crop_blocks + dst_blk_y < comp_height) { /* Row is within the mirrorable area. */ - dst_row_ptr = dst_buffer[offset_y]; src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; - /* Process the blocks that can be mirrored both ways. */ - for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; - for (i = 0; i < DCTSIZE; i += 2) { - /* For even row, negate every odd column. */ - for (j = 0; j < DCTSIZE; j += 2) { - *dst_ptr++ = *src_ptr++; - *dst_ptr++ = - *src_ptr++; + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Process the blocks that can be mirrored both ways. */ + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE; i += 2) { + /* For even row, negate every odd column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } + /* For odd row, negate every even column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = - *src_ptr++; + *dst_ptr++ = *src_ptr++; + } } - /* For odd row, negate every even column. */ - for (j = 0; j < DCTSIZE; j += 2) { - *dst_ptr++ = - *src_ptr++; - *dst_ptr++ = *src_ptr++; + } else { + /* Any remaining right-edge blocks are only mirrored vertically. */ + src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = - *src_ptr++; } } } - /* Any remaining right-edge blocks are only mirrored vertically. */ - for (; dst_blk_x < compptr->width_in_data_units; dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[dst_blk_x]; - for (i = 0; i < DCTSIZE; i += 2) { - for (j = 0; j < DCTSIZE; j++) - *dst_ptr++ = *src_ptr++; - for (j = 0; j < DCTSIZE; j++) - *dst_ptr++ = - *src_ptr++; - } - } } else { /* Remaining rows are just mirrored horizontally. */ - dst_row_ptr = dst_buffer[offset_y]; src_row_ptr = src_buffer[offset_y]; - /* Process the blocks that can be mirrored. */ - for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; - for (i = 0; i < DCTSIZE2; i += 2) { - *dst_ptr++ = *src_ptr++; - *dst_ptr++ = - *src_ptr++; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Process the blocks that can be mirrored. */ + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE2; i += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } + } else { + /* Any remaining right-edge blocks are only copied. */ + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, + dst_row_ptr + dst_blk_x, + (JDIMENSION) 1); } } - /* Any remaining right-edge blocks are only copied. */ - for (; dst_blk_x < compptr->width_in_data_units; dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[dst_blk_x]; - for (i = 0; i < DCTSIZE2; i++) - *dst_ptr++ = *src_ptr++; - } } } } @@ -457,6 +742,7 @@ do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, LOCAL(void) do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) /* Transverse transpose is equivalent to @@ -470,37 +756,51 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, */ { JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; int ci, i, j, offset_x, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_height / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_width = MCU_cols * compptr->h_samp_factor; comp_height = MCU_rows * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) { - src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, - (JDIMENSION) compptr->h_samp_factor, FALSE); + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_width - x_crop_blocks - dst_blk_x - + (JDIMENSION) compptr->h_samp_factor, + (JDIMENSION) compptr->h_samp_factor, FALSE); + } else { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION) compptr->h_samp_factor, FALSE); + } for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { - if (dst_blk_y < comp_height) { - src_ptr = src_buffer[offset_x] - [comp_height - dst_blk_y - offset_y - 1]; - if (dst_blk_x < comp_width) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (y_crop_blocks + dst_blk_y < comp_height) { + if (x_crop_blocks + dst_blk_x < comp_width) { /* Block is within the mirrorable area. */ - dst_ptr = dst_buffer[offset_y] - [comp_width - dst_blk_x - offset_x - 1]; + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) { dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -516,7 +816,8 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, } } else { /* Right-edge blocks are mirrored in y only */ - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + src_ptr = src_buffer[offset_x] + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) { dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -526,11 +827,10 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, } } } else { - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; - if (dst_blk_x < comp_width) { + if (x_crop_blocks + dst_blk_x < comp_width) { /* Bottom-edge blocks are mirrored in x only */ - dst_ptr = dst_buffer[offset_y] - [comp_width - dst_blk_x - offset_x - 1]; + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [dst_blk_y + offset_y + y_crop_blocks]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -540,7 +840,8 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, } } else { /* At lower right corner, just transpose, no mirroring */ - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; @@ -554,7 +855,123 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, } +/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. + * Returns TRUE if valid integer found, FALSE if not. + * *strptr is advanced over the digit string, and *result is set to its value. + */ + +LOCAL(boolean) +jt_read_integer (const char ** strptr, JDIMENSION * result) +{ + const char * ptr = *strptr; + JDIMENSION val = 0; + + for (; isdigit(*ptr); ptr++) { + val = val * 10 + (JDIMENSION) (*ptr - '0'); + } + *result = val; + if (ptr == *strptr) + return FALSE; /* oops, no digits */ + *strptr = ptr; + return TRUE; +} + + +/* Parse a crop specification (written in X11 geometry style). + * The routine returns TRUE if the spec string is valid, FALSE if not. + * + * The crop spec string should have the format + * [f]x[f]{+-}{+-} + * where width, height, xoffset, and yoffset are unsigned integers. + * Each of the elements can be omitted to indicate a default value. + * (A weakness of this style is that it is not possible to omit xoffset + * while specifying yoffset, since they look alike.) + * + * This code is loosely based on XParseGeometry from the X11 distribution. + */ + +GLOBAL(boolean) +jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec) +{ + info->crop = FALSE; + info->crop_width_set = JCROP_UNSET; + info->crop_height_set = JCROP_UNSET; + info->crop_xoffset_set = JCROP_UNSET; + info->crop_yoffset_set = JCROP_UNSET; + + if (isdigit(*spec)) { + /* fetch width */ + if (! jt_read_integer(&spec, &info->crop_width)) + return FALSE; + if (*spec == 'f' || *spec == 'F') { + spec++; + info->crop_width_set = JCROP_FORCE; + } else + info->crop_width_set = JCROP_POS; + } + if (*spec == 'x' || *spec == 'X') { + /* fetch height */ + spec++; + if (! jt_read_integer(&spec, &info->crop_height)) + return FALSE; + if (*spec == 'f' || *spec == 'F') { + spec++; + info->crop_height_set = JCROP_FORCE; + } else + info->crop_height_set = JCROP_POS; + } + if (*spec == '+' || *spec == '-') { + /* fetch xoffset */ + info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; + spec++; + if (! jt_read_integer(&spec, &info->crop_xoffset)) + return FALSE; + } + if (*spec == '+' || *spec == '-') { + /* fetch yoffset */ + info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; + spec++; + if (! jt_read_integer(&spec, &info->crop_yoffset)) + return FALSE; + } + /* We had better have gotten to the end of the string. */ + if (*spec != '\0') + return FALSE; + info->crop = TRUE; + return TRUE; +} + + +/* Trim off any partial iMCUs on the indicated destination edge */ + +LOCAL(void) +trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) +{ + JDIMENSION MCU_cols; + + MCU_cols = info->output_width / info->iMCU_sample_width; + if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == + full_width / info->iMCU_sample_width) + info->output_width = MCU_cols * info->iMCU_sample_width; +} + +LOCAL(void) +trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) +{ + JDIMENSION MCU_rows; + + MCU_rows = info->output_height / info->iMCU_sample_height; + if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == + full_height / info->iMCU_sample_height) + info->output_height = MCU_rows * info->iMCU_sample_height; +} + + /* Request any required workspace. + * + * This routine figures out the size that the output image will be + * (which implies that all the transform parameters must be set before + * it is called). * * We allocate the workspace virtual arrays from the source decompression * object, so that all the arrays (both the original data and the workspace) @@ -562,75 +979,290 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * Hence, this routine must be called after jpeg_read_header (which reads * the image dimensions) and before jpeg_read_coefficients (which realizes * the source's virtual arrays). + * + * This function returns FALSE right away if -perfect is given + * and transformation is not perfect. Otherwise returns TRUE. */ -GLOBAL(void) +GLOBAL(boolean) jtransform_request_workspace (j_decompress_ptr srcinfo, jpeg_transform_info *info) { - jvirt_barray_ptr *coef_arrays = NULL; + jvirt_barray_ptr *coef_arrays; + boolean need_workspace, transpose_it; jpeg_component_info *compptr; - int ci; + JDIMENSION xoffset, yoffset; + JDIMENSION width_in_iMCUs, height_in_iMCUs; + JDIMENSION width_in_blocks, height_in_blocks; + int ci, h_samp_factor, v_samp_factor; + /* Determine number of components in output image */ if (info->force_grayscale && - srcinfo->jpeg_color_space == JCS_YCbCr && - srcinfo->num_components == 3) { + (srcinfo->jpeg_color_space == JCS_YCbCr || + srcinfo->jpeg_color_space == JCS_BG_YCC) && + srcinfo->num_components == 3) /* We'll only process the first component */ info->num_components = 1; - } else { + else /* Process all the components */ info->num_components = srcinfo->num_components; + + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(srcinfo); + + /* Return right away if -perfect is given and transformation is not perfect. + */ + if (info->perfect) { + if (info->num_components == 1) { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->min_DCT_h_scaled_size, + srcinfo->min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } else { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } } + /* If there is only one output component, force the iMCU size to be 1; + * else use the source iMCU size. (This allows us to do the right thing + * when reducing color to grayscale, and also provides a handy way of + * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) + */ switch (info->transform) { - case JXFORM_NONE: - case JXFORM_FLIP_H: - /* Don't need a workspace array */ - break; - case JXFORM_FLIP_V: - case JXFORM_ROT_180: - /* Need workspace arrays having same dimensions as source image. - * Note that we allocate arrays padded out to the next iMCU boundary, - * so that transform routines need not worry about missing edge blocks. - */ - coef_arrays = (jvirt_barray_ptr *) - (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, - SIZEOF(jvirt_barray_ptr) * info->num_components); - for (ci = 0; ci < info->num_components; ci++) { - compptr = srcinfo->comp_info + ci; - coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) - ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_data_units, - (long) compptr->v_samp_factor), - (JDIMENSION) compptr->v_samp_factor); - } - break; case JXFORM_TRANSPOSE: case JXFORM_TRANSVERSE: case JXFORM_ROT_90: case JXFORM_ROT_270: - /* Need workspace arrays having transposed dimensions. - * Note that we allocate arrays padded out to the next iMCU boundary, - * so that transform routines need not worry about missing edge blocks. - */ - coef_arrays = (jvirt_barray_ptr *) - (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, - SIZEOF(jvirt_barray_ptr) * info->num_components); - for (ci = 0; ci < info->num_components; ci++) { - compptr = srcinfo->comp_info + ci; - coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) - ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, - (JDIMENSION) jround_up((long) compptr->height_in_data_units, - (long) compptr->v_samp_factor), - (JDIMENSION) jround_up((long) compptr->width_in_data_units, - (long) compptr->h_samp_factor), - (JDIMENSION) compptr->h_samp_factor); + info->output_width = srcinfo->output_height; + info->output_height = srcinfo->output_width; + if (info->num_components == 1) { + info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; + info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; + } else { + info->iMCU_sample_width = + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; + info->iMCU_sample_height = + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; + } + break; + default: + info->output_width = srcinfo->output_width; + info->output_height = srcinfo->output_height; + if (info->num_components == 1) { + info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; + info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; + } else { + info->iMCU_sample_width = + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; + info->iMCU_sample_height = + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; } break; } - info->workspace_coef_arrays = coef_arrays; + + /* If cropping has been requested, compute the crop area's position and + * dimensions, ensuring that its upper left corner falls at an iMCU boundary. + */ + if (info->crop) { + /* Insert default values for unset crop parameters */ + if (info->crop_xoffset_set == JCROP_UNSET) + info->crop_xoffset = 0; /* default to +0 */ + if (info->crop_yoffset_set == JCROP_UNSET) + info->crop_yoffset = 0; /* default to +0 */ + if (info->crop_width_set == JCROP_UNSET) { + if (info->crop_xoffset >= info->output_width) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + info->crop_width = info->output_width - info->crop_xoffset; + } else { + /* Check for crop extension */ + if (info->crop_width > info->output_width) { + /* Crop extension does not work when transforming! */ + if (info->transform != JXFORM_NONE || + info->crop_xoffset >= info->crop_width || + info->crop_xoffset > info->crop_width - info->output_width) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + } else { + if (info->crop_xoffset >= info->output_width || + info->crop_width <= 0 || + info->crop_xoffset > info->output_width - info->crop_width) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + } + } + if (info->crop_height_set == JCROP_UNSET) { + if (info->crop_yoffset >= info->output_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + info->crop_height = info->output_height - info->crop_yoffset; + } else { + /* Check for crop extension */ + if (info->crop_height > info->output_height) { + /* Crop extension does not work when transforming! */ + if (info->transform != JXFORM_NONE || + info->crop_yoffset >= info->crop_height || + info->crop_yoffset > info->crop_height - info->output_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + } else { + if (info->crop_yoffset >= info->output_height || + info->crop_height <= 0 || + info->crop_yoffset > info->output_height - info->crop_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + } + } + /* Convert negative crop offsets into regular offsets */ + if (info->crop_xoffset_set != JCROP_NEG) + xoffset = info->crop_xoffset; + else if (info->crop_width > info->output_width) /* crop extension */ + xoffset = info->crop_width - info->output_width - info->crop_xoffset; + else + xoffset = info->output_width - info->crop_width - info->crop_xoffset; + if (info->crop_yoffset_set != JCROP_NEG) + yoffset = info->crop_yoffset; + else if (info->crop_height > info->output_height) /* crop extension */ + yoffset = info->crop_height - info->output_height - info->crop_yoffset; + else + yoffset = info->output_height - info->crop_height - info->crop_yoffset; + /* Now adjust so that upper left corner falls at an iMCU boundary */ + if (info->transform == JXFORM_WIPE) { + /* Ensure the effective wipe region will cover the requested */ + info->drop_width = (JDIMENSION) jdiv_round_up + ((long) (info->crop_width + (xoffset % info->iMCU_sample_width)), + (long) info->iMCU_sample_width); + info->drop_height = (JDIMENSION) jdiv_round_up + ((long) (info->crop_height + (yoffset % info->iMCU_sample_height)), + (long) info->iMCU_sample_height); + } else { + /* Ensure the effective crop region will cover the requested */ + if (info->crop_width_set == JCROP_FORCE || + info->crop_width > info->output_width) + info->output_width = info->crop_width; + else + info->output_width = + info->crop_width + (xoffset % info->iMCU_sample_width); + if (info->crop_height_set == JCROP_FORCE || + info->crop_height > info->output_height) + info->output_height = info->crop_height; + else + info->output_height = + info->crop_height + (yoffset % info->iMCU_sample_height); + } + /* Save x/y offsets measured in iMCUs */ + info->x_crop_offset = xoffset / info->iMCU_sample_width; + info->y_crop_offset = yoffset / info->iMCU_sample_height; + } else { + info->x_crop_offset = 0; + info->y_crop_offset = 0; + } + + /* Figure out whether we need workspace arrays, + * and if so whether they are transposed relative to the source. + */ + need_workspace = FALSE; + transpose_it = FALSE; + switch (info->transform) { + case JXFORM_NONE: + if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || + info->output_width > srcinfo->output_width || + info->output_height > srcinfo->output_height) + need_workspace = TRUE; + /* No workspace needed if neither cropping nor transforming */ + break; + case JXFORM_FLIP_H: + if (info->trim) + trim_right_edge(info, srcinfo->output_width); + if (info->y_crop_offset != 0) + need_workspace = TRUE; + /* do_flip_h_no_crop doesn't need a workspace array */ + break; + case JXFORM_FLIP_V: + if (info->trim) + trim_bottom_edge(info, srcinfo->output_height); + /* Need workspace arrays having same dimensions as source image. */ + need_workspace = TRUE; + break; + case JXFORM_TRANSPOSE: + /* transpose does NOT have to trim anything */ + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_TRANSVERSE: + if (info->trim) { + trim_right_edge(info, srcinfo->output_height); + trim_bottom_edge(info, srcinfo->output_width); + } + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_ROT_90: + if (info->trim) + trim_right_edge(info, srcinfo->output_height); + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_ROT_180: + if (info->trim) { + trim_right_edge(info, srcinfo->output_width); + trim_bottom_edge(info, srcinfo->output_height); + } + /* Need workspace arrays having same dimensions as source image. */ + need_workspace = TRUE; + break; + case JXFORM_ROT_270: + if (info->trim) + trim_bottom_edge(info, srcinfo->output_width); + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_WIPE: + break; + } + + /* Allocate workspace if needed. + * Note that we allocate arrays padded out to the next iMCU boundary, + * so that transform routines need not worry about missing edge blocks. + */ + if (need_workspace) { + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, + SIZEOF(jvirt_barray_ptr) * info->num_components); + width_in_iMCUs = (JDIMENSION) + jdiv_round_up((long) info->output_width, + (long) info->iMCU_sample_width); + height_in_iMCUs = (JDIMENSION) + jdiv_round_up((long) info->output_height, + (long) info->iMCU_sample_height); + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + if (info->num_components == 1) { + /* we're going to force samp factors to 1x1 in this case */ + h_samp_factor = v_samp_factor = 1; + } else if (transpose_it) { + h_samp_factor = compptr->v_samp_factor; + v_samp_factor = compptr->h_samp_factor; + } else { + h_samp_factor = compptr->h_samp_factor; + v_samp_factor = compptr->v_samp_factor; + } + width_in_blocks = width_in_iMCUs * h_samp_factor; + height_in_blocks = height_in_iMCUs * v_samp_factor; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, + width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); + } + info->workspace_coef_arrays = coef_arrays; + } else + info->workspace_coef_arrays = NULL; + + return TRUE; } @@ -642,13 +1274,16 @@ transpose_critical_parameters (j_compress_ptr dstinfo) int tblno, i, j, ci, itemp; jpeg_component_info *compptr; JQUANT_TBL *qtblptr; - JDIMENSION dtemp; + JDIMENSION jtemp; UINT16 qtemp; - /* Transpose basic image dimensions */ - dtemp = dstinfo->image_width; + /* Transpose image dimensions */ + jtemp = dstinfo->image_width; dstinfo->image_width = dstinfo->image_height; - dstinfo->image_height = dtemp; + dstinfo->image_height = jtemp; + itemp = dstinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; + dstinfo->min_DCT_v_scaled_size = itemp; /* Transpose sampling factors */ for (ci = 0; ci < dstinfo->num_components; ci++) { @@ -674,46 +1309,159 @@ transpose_critical_parameters (j_compress_ptr dstinfo) } -/* Trim off any partial iMCUs on the indicated destination edge */ +/* Adjust Exif image parameters. + * + * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. + */ LOCAL(void) -trim_right_edge (j_compress_ptr dstinfo) +adjust_exif_parameters (JOCTET FAR * data, unsigned int length, + JDIMENSION new_width, JDIMENSION new_height) { - int ci, max_h_samp_factor; - JDIMENSION MCU_cols; + boolean is_motorola; /* Flag for byte order */ + unsigned int number_of_tags, tagnum; + unsigned int firstoffset, offset; + JDIMENSION new_value; - /* We have to compute max_h_samp_factor ourselves, - * because it hasn't been set yet in the destination - * (and we don't want to use the source's value). - */ - max_h_samp_factor = 1; - for (ci = 0; ci < dstinfo->num_components; ci++) { - int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor; - max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor); + if (length < 12) return; /* Length of an IFD entry */ + + /* Discover byte order */ + if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) + is_motorola = FALSE; + else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) + is_motorola = TRUE; + else + return; + + /* Check Tag Mark */ + if (is_motorola) { + if (GETJOCTET(data[2]) != 0) return; + if (GETJOCTET(data[3]) != 0x2A) return; + } else { + if (GETJOCTET(data[3]) != 0) return; + if (GETJOCTET(data[2]) != 0x2A) return; } - MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE); - if (MCU_cols > 0) /* can't trim to 0 pixels */ - dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE); -} -LOCAL(void) -trim_bottom_edge (j_compress_ptr dstinfo) -{ - int ci, max_v_samp_factor; - JDIMENSION MCU_rows; - - /* We have to compute max_v_samp_factor ourselves, - * because it hasn't been set yet in the destination - * (and we don't want to use the source's value). - */ - max_v_samp_factor = 1; - for (ci = 0; ci < dstinfo->num_components; ci++) { - int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor; - max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor); + /* Get first IFD offset (offset to IFD0) */ + if (is_motorola) { + if (GETJOCTET(data[4]) != 0) return; + if (GETJOCTET(data[5]) != 0) return; + firstoffset = GETJOCTET(data[6]); + firstoffset <<= 8; + firstoffset += GETJOCTET(data[7]); + } else { + if (GETJOCTET(data[7]) != 0) return; + if (GETJOCTET(data[6]) != 0) return; + firstoffset = GETJOCTET(data[5]); + firstoffset <<= 8; + firstoffset += GETJOCTET(data[4]); } - MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE); - if (MCU_rows > 0) /* can't trim to 0 pixels */ - dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE); + if (firstoffset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this IFD */ + if (is_motorola) { + number_of_tags = GETJOCTET(data[firstoffset]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[firstoffset+1]); + } else { + number_of_tags = GETJOCTET(data[firstoffset+1]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[firstoffset]); + } + if (number_of_tags == 0) return; + firstoffset += 2; + + /* Search for ExifSubIFD offset Tag in IFD0 */ + for (;;) { + if (firstoffset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = GETJOCTET(data[firstoffset]); + tagnum <<= 8; + tagnum += GETJOCTET(data[firstoffset+1]); + } else { + tagnum = GETJOCTET(data[firstoffset+1]); + tagnum <<= 8; + tagnum += GETJOCTET(data[firstoffset]); + } + if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ + if (--number_of_tags == 0) return; + firstoffset += 12; + } + + /* Get the ExifSubIFD offset */ + if (is_motorola) { + if (GETJOCTET(data[firstoffset+8]) != 0) return; + if (GETJOCTET(data[firstoffset+9]) != 0) return; + offset = GETJOCTET(data[firstoffset+10]); + offset <<= 8; + offset += GETJOCTET(data[firstoffset+11]); + } else { + if (GETJOCTET(data[firstoffset+11]) != 0) return; + if (GETJOCTET(data[firstoffset+10]) != 0) return; + offset = GETJOCTET(data[firstoffset+9]); + offset <<= 8; + offset += GETJOCTET(data[firstoffset+8]); + } + if (offset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this SubIFD */ + if (is_motorola) { + number_of_tags = GETJOCTET(data[offset]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[offset+1]); + } else { + number_of_tags = GETJOCTET(data[offset+1]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[offset]); + } + if (number_of_tags < 2) return; + offset += 2; + + /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ + do { + if (offset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = GETJOCTET(data[offset]); + tagnum <<= 8; + tagnum += GETJOCTET(data[offset+1]); + } else { + tagnum = GETJOCTET(data[offset+1]); + tagnum <<= 8; + tagnum += GETJOCTET(data[offset]); + } + if (tagnum == 0xA002 || tagnum == 0xA003) { + if (tagnum == 0xA002) + new_value = new_width; /* ExifImageWidth Tag */ + else + new_value = new_height; /* ExifImageHeight Tag */ + if (is_motorola) { + data[offset+2] = 0; /* Format = unsigned long (4 octets) */ + data[offset+3] = 4; + data[offset+4] = 0; /* Number Of Components = 1 */ + data[offset+5] = 0; + data[offset+6] = 0; + data[offset+7] = 1; + data[offset+8] = 0; + data[offset+9] = 0; + data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); + data[offset+11] = (JOCTET)(new_value & 0xFF); + } else { + data[offset+2] = 4; /* Format = unsigned long (4 octets) */ + data[offset+3] = 0; + data[offset+4] = 1; /* Number Of Components = 1 */ + data[offset+5] = 0; + data[offset+6] = 0; + data[offset+7] = 0; + data[offset+8] = (JOCTET)(new_value & 0xFF); + data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); + data[offset+10] = 0; + data[offset+11] = 0; + } + } + offset += 12; + } while (--number_of_tags); } @@ -736,18 +1484,23 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo, { /* If force-to-grayscale is requested, adjust destination parameters */ if (info->force_grayscale) { - /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed - * properly. Among other things, the target h_samp_factor & v_samp_factor - * will get set to 1, which typically won't match the source. - * In fact we do this even if the source is already grayscale; that - * provides an easy way of coercing a grayscale JPEG with funny sampling - * factors to the customary 1,1. (Some decoders fail on other factors.) + /* First, ensure we have YCC or grayscale data, and that the source's + * Y channel is full resolution. (No reasonable person would make Y + * be less than full resolution, so actually coping with that case + * isn't worth extra code space. But we check it to avoid crashing.) */ - if ((dstinfo->jpeg_color_space == JCS_YCbCr && - dstinfo->num_components == 3) || - (dstinfo->jpeg_color_space == JCS_GRAYSCALE && - dstinfo->num_components == 1)) { - /* We have to preserve the source's quantization table number. */ + if ((((dstinfo->jpeg_color_space == JCS_YCbCr || + dstinfo->jpeg_color_space == JCS_BG_YCC) && + dstinfo->num_components == 3) || + (dstinfo->jpeg_color_space == JCS_GRAYSCALE && + dstinfo->num_components == 1)) && + srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && + srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { + /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed + * properly. Among other things, it sets the target h_samp_factor & + * v_samp_factor to 1, which typically won't match the source. + * We have to preserve the source's quantization table number, however. + */ int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; @@ -755,48 +1508,52 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo, /* Sorry, can't do it */ ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); } + } else if (info->num_components == 1) { + /* For a single-component source, we force the destination sampling factors + * to 1x1, with or without force_grayscale. This is useful because some + * decoders choke on grayscale images with other sampling factors. + */ + dstinfo->comp_info[0].h_samp_factor = 1; + dstinfo->comp_info[0].v_samp_factor = 1; } - /* Correct the destination's image dimensions etc if necessary */ + /* Correct the destination's image dimensions as necessary + * for rotate/flip, resize, and crop operations. + */ + dstinfo->jpeg_width = info->output_width; + dstinfo->jpeg_height = info->output_height; + + /* Transpose destination image parameters */ switch (info->transform) { - case JXFORM_NONE: - /* Nothing to do */ - break; - case JXFORM_FLIP_H: - if (info->trim) - trim_right_edge(dstinfo); - break; - case JXFORM_FLIP_V: - if (info->trim) - trim_bottom_edge(dstinfo); - break; case JXFORM_TRANSPOSE: - transpose_critical_parameters(dstinfo); - /* transpose does NOT have to trim anything */ - break; case JXFORM_TRANSVERSE: - transpose_critical_parameters(dstinfo); - if (info->trim) { - trim_right_edge(dstinfo); - trim_bottom_edge(dstinfo); - } - break; case JXFORM_ROT_90: - transpose_critical_parameters(dstinfo); - if (info->trim) - trim_right_edge(dstinfo); - break; - case JXFORM_ROT_180: - if (info->trim) { - trim_right_edge(dstinfo); - trim_bottom_edge(dstinfo); - } - break; case JXFORM_ROT_270: transpose_critical_parameters(dstinfo); - if (info->trim) - trim_bottom_edge(dstinfo); break; + default: + break; + } + + /* Adjust Exif properties */ + if (srcinfo->marker_list != NULL && + srcinfo->marker_list->marker == JPEG_APP0+1 && + srcinfo->marker_list->data_length >= 6 && + GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && + GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && + GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && + GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && + GETJOCTET(srcinfo->marker_list->data[4]) == 0 && + GETJOCTET(srcinfo->marker_list->data[5]) == 0) { + /* Suppress output of JFIF marker */ + dstinfo->write_JFIF_header = FALSE; + /* Adjust Exif image parameters */ + if (dstinfo->jpeg_width != srcinfo->image_width || + dstinfo->jpeg_height != srcinfo->image_height) + /* Align data segment to start of TIFF structure for parsing */ + adjust_exif_parameters(srcinfo->marker_list->data + 6, + srcinfo->marker_list->data_length - 6, + dstinfo->jpeg_width, dstinfo->jpeg_height); } /* Return the appropriate output data set */ @@ -816,40 +1573,118 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo, */ GLOBAL(void) -jtransform_execute_transformation (j_decompress_ptr srcinfo, - j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info) +jtransform_execute_transform (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) { jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; + /* Note: conditions tested here should match those in switch statement + * in jtransform_request_workspace() + */ switch (info->transform) { case JXFORM_NONE: + if (info->output_width > srcinfo->output_width || + info->output_height > srcinfo->output_height) + do_crop_ext(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + else if (info->x_crop_offset != 0 || info->y_crop_offset != 0) + do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); break; case JXFORM_FLIP_H: - do_flip_h(srcinfo, dstinfo, src_coef_arrays); + if (info->y_crop_offset != 0) + do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + else + do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, + src_coef_arrays); break; case JXFORM_FLIP_V: - do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); break; case JXFORM_TRANSPOSE: - do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); break; case JXFORM_TRANSVERSE: - do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); break; case JXFORM_ROT_90: - do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); break; case JXFORM_ROT_180: - do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); break; case JXFORM_ROT_270: - do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_WIPE: + do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, info->drop_width, info->drop_height); break; } } +/* jtransform_perfect_transform + * + * Determine whether lossless transformation is perfectly + * possible for a specified image and transformation. + * + * Inputs: + * image_width, image_height: source image dimensions. + * MCU_width, MCU_height: pixel dimensions of MCU. + * transform: transformation identifier. + * Parameter sources from initialized jpeg_struct + * (after reading source header): + * image_width = cinfo.image_width + * image_height = cinfo.image_height + * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size + * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size + * Result: + * TRUE = perfect transformation possible + * FALSE = perfect transformation not possible + * (may use custom action then) + */ + +GLOBAL(boolean) +jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, + int MCU_width, int MCU_height, + JXFORM_CODE transform) +{ + boolean result = TRUE; /* initialize TRUE */ + + switch (transform) { + case JXFORM_FLIP_H: + case JXFORM_ROT_270: + if (image_width % (JDIMENSION) MCU_width) + result = FALSE; + break; + case JXFORM_FLIP_V: + case JXFORM_ROT_90: + if (image_height % (JDIMENSION) MCU_height) + result = FALSE; + break; + case JXFORM_TRANSVERSE: + case JXFORM_ROT_180: + if (image_width % (JDIMENSION) MCU_width) + result = FALSE; + if (image_height % (JDIMENSION) MCU_height) + result = FALSE; + break; + default: + break; + } + + return result; +} + #endif /* TRANSFORMS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/transupp.h b/uppsrc/plugin/jpg/lib/transupp.h index eb0b05566..28a1a9cb7 100644 --- a/uppsrc/plugin/jpg/lib/transupp.h +++ b/uppsrc/plugin/jpg/lib/transupp.h @@ -1,7 +1,7 @@ /* * transupp.h * - * Copyright (C) 1997, Thomas G. Lane. + * Copyright (C) 1997-2013, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -22,32 +22,6 @@ #define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ #endif -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jtransform_request_workspace jTrRequest -#define jtransform_adjust_parameters jTrAdjust -#define jtransform_execute_transformation jTrExec -#define jcopy_markers_setup jCMrkSetup -#define jcopy_markers_execute jCMrkExec -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * Codes for supported types of image transformations. - */ - -typedef enum { - JXFORM_NONE, /* no transformation */ - JXFORM_FLIP_H, /* horizontal flip */ - JXFORM_FLIP_V, /* vertical flip */ - JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ - JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ - JXFORM_ROT_90, /* 90-degree clockwise rotation */ - JXFORM_ROT_180, /* 180-degree rotation */ - JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ -} JXFORM_CODE; - /* * Although rotating and flipping data expressed as DCT coefficients is not * hard, there is an asymmetry in the JPEG format specification for images @@ -75,6 +49,28 @@ typedef enum { * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim * followed by -rot 180 -trim trims both edges.) * + * We also offer a lossless-crop option, which discards data outside a given + * image region but losslessly preserves what is inside. Like the rotate and + * flip transforms, lossless crop is restricted by the current JPEG format: the + * upper left corner of the selected region must fall on an iMCU boundary. If + * this does not hold for the given crop parameters, we silently move the upper + * left corner up and/or left to make it so, simultaneously increasing the + * region dimensions to keep the lower right crop corner unchanged. (Thus, the + * output image covers at least the requested region, but may cover more.) + * The adjustment of the region dimensions may be optionally disabled. + * + * A complementary lossless-wipe option is provided to discard (gray out) data + * inside a given image region while losslessly preserving what is outside. + * + * We also provide a lossless-resize option, which is kind of a lossless-crop + * operation in the DCT coefficient block domain - it discards higher-order + * coefficients and losslessly preserves lower-order coefficients of a + * sub-block. + * + * Rotate/flip transform, resize, and crop can be requested together in a + * single invocation. The crop is applied last --- that is, the crop region + * is specified in terms of the destination image after transform/resize. + * * We also offer a "force to grayscale" option, which simply discards the * chrominance channels of a YCbCr image. This is lossless in the sense that * the luminance channel is preserved exactly. It's not the same kind of @@ -83,22 +79,96 @@ typedef enum { * be aware of the option to know how many components to work on. */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jtransform_parse_crop_spec jTrParCrop +#define jtransform_request_workspace jTrRequest +#define jtransform_adjust_parameters jTrAdjust +#define jtransform_execute_transform jTrExec +#define jtransform_perfect_transform jTrPerfect +#define jcopy_markers_setup jCMrkSetup +#define jcopy_markers_execute jCMrkExec +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * Codes for supported types of image transformations. + */ + +typedef enum { + JXFORM_NONE, /* no transformation */ + JXFORM_FLIP_H, /* horizontal flip */ + JXFORM_FLIP_V, /* vertical flip */ + JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ + JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ + JXFORM_ROT_90, /* 90-degree clockwise rotation */ + JXFORM_ROT_180, /* 180-degree rotation */ + JXFORM_ROT_270, /* 270-degree clockwise (or 90 ccw) */ + JXFORM_WIPE /* wipe */ +} JXFORM_CODE; + +/* + * Codes for crop parameters, which can individually be unspecified, + * positive or negative for xoffset or yoffset, + * positive or forced for width or height. + */ + +typedef enum { + JCROP_UNSET, + JCROP_POS, + JCROP_NEG, + JCROP_FORCE +} JCROP_CODE; + +/* + * Transform parameters struct. + * NB: application must not change any elements of this struct after + * calling jtransform_request_workspace. + */ + typedef struct { /* Options: set by caller */ JXFORM_CODE transform; /* image transform operator */ + boolean perfect; /* if TRUE, fail if partial MCUs are requested */ boolean trim; /* if TRUE, trim partial MCUs as needed */ boolean force_grayscale; /* if TRUE, convert color image to grayscale */ + boolean crop; /* if TRUE, crop or wipe source image */ + + /* Crop parameters: application need not set these unless crop is TRUE. + * These can be filled in by jtransform_parse_crop_spec(). + */ + JDIMENSION crop_width; /* Width of selected region */ + JCROP_CODE crop_width_set; /* (forced disables adjustment) */ + JDIMENSION crop_height; /* Height of selected region */ + JCROP_CODE crop_height_set; /* (forced disables adjustment) */ + JDIMENSION crop_xoffset; /* X offset of selected region */ + JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */ + JDIMENSION crop_yoffset; /* Y offset of selected region */ + JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */ /* Internal workspace: caller should not touch these */ int num_components; /* # of components in workspace */ jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ + JDIMENSION output_width; /* cropped destination dimensions */ + JDIMENSION output_height; + JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */ + JDIMENSION y_crop_offset; + JDIMENSION drop_width; /* drop/wipe dimensions measured in iMCUs */ + JDIMENSION drop_height; + int iMCU_sample_width; /* destination iMCU size */ + int iMCU_sample_height; } jpeg_transform_info; #if TRANSFORMS_SUPPORTED +/* Parse a crop specification (written in X11 geometry style) */ +EXTERN(boolean) jtransform_parse_crop_spec + JPP((jpeg_transform_info *info, const char *spec)); /* Request any required workspace */ -EXTERN(void) jtransform_request_workspace +EXTERN(boolean) jtransform_request_workspace JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); /* Adjust output image parameters */ EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters @@ -106,10 +176,24 @@ EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters jvirt_barray_ptr *src_coef_arrays, jpeg_transform_info *info)); /* Execute the actual transformation, if any */ -EXTERN(void) jtransform_execute_transformation +EXTERN(void) jtransform_execute_transform JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jpeg_transform_info *info)); +/* Determine whether lossless transformation is perfectly + * possible for a specified image and transformation. + */ +EXTERN(boolean) jtransform_perfect_transform + JPP((JDIMENSION image_width, JDIMENSION image_height, + int MCU_width, int MCU_height, + JXFORM_CODE transform)); + +/* jtransform_execute_transform used to be called + * jtransform_execute_transformation, but some compilers complain about + * routine names that long. This macro is here to avoid breaking any + * old source code that uses the original name... + */ +#define jtransform_execute_transformation jtransform_execute_transform #endif /* TRANSFORMS_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/wrbmp.c b/uppsrc/plugin/jpg/lib/wrbmp.c index 76edc874d..2b8146e2c 100644 --- a/uppsrc/plugin/jpg/lib/wrbmp.c +++ b/uppsrc/plugin/jpg/lib/wrbmp.c @@ -189,7 +189,7 @@ write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest) /* File size */ headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */ bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height; - + /* Set unused fields of header to 0 */ MEMZERO(bmpfileheader, SIZEOF(bmpfileheader)); MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader)); @@ -254,7 +254,7 @@ write_os2_header (j_decompress_ptr cinfo, bmp_dest_ptr dest) /* File size */ headersize = 14 + 12 + cmap_entries * 3; /* Header and colormap */ bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height; - + /* Set unused fields of header to 0 */ MEMZERO(bmpfileheader, SIZEOF(bmpfileheader)); MEMZERO(bmpcoreheader, SIZEOF(bmpcoreheader)); @@ -327,7 +327,7 @@ write_colormap (j_decompress_ptr cinfo, bmp_dest_ptr dest, putc(0, outfile); } } - /* Pad colormap with zeros to ensure specified number of colormap entries */ + /* Pad colormap with zeros to ensure specified number of colormap entries */ if (i > map_colors) ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i); for (; i < map_colors; i++) { diff --git a/uppsrc/plugin/jpg/lib/wrgif.c b/uppsrc/plugin/jpg/lib/wrgif.c index 13f953b56..d38a42bf4 100644 --- a/uppsrc/plugin/jpg/lib/wrgif.c +++ b/uppsrc/plugin/jpg/lib/wrgif.c @@ -2,6 +2,7 @@ * wrgif.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -218,7 +219,7 @@ put_3bytes (gif_dest_ptr dinfo, int val) LOCAL(void) emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap) /* Output the GIF file header, including color map */ -/* If colormap==NULL, synthesize a gray-scale colormap */ +/* If colormap==NULL, synthesize a grayscale colormap */ { int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte; int cshift = dinfo->cinfo->data_precision - 8; @@ -270,7 +271,7 @@ emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap) put_3bytes(dinfo, GETJSAMPLE(colormap[0][i]) >> cshift); } } else { - /* Create a gray-scale map of num_colors values, range 0..255 */ + /* Create a grayscale map of num_colors values, range 0..255 */ put_3bytes(dinfo, (i * 255 + (num_colors-1)/2) / (num_colors-1)); } } else { @@ -393,7 +394,7 @@ jinit_write_gif (j_decompress_ptr cinfo) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1); dest->pub.buffer_height = 1; - return (djpeg_dest_ptr) dest; + return &dest->pub; } #endif /* GIF_SUPPORTED */ diff --git a/uppsrc/plugin/jpg/lib/wrjpgcom.c b/uppsrc/plugin/jpg/lib/wrjpgcom.c index 7d10ee66e..66dccee63 100644 --- a/uppsrc/plugin/jpg/lib/wrjpgcom.c +++ b/uppsrc/plugin/jpg/lib/wrjpgcom.c @@ -2,6 +2,7 @@ * wrjpgcom.c * * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -453,6 +454,11 @@ main (int argc, char **argv) comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH); if (comment_arg == NULL) ERREXIT("Insufficient memory"); + if (strlen(argv[argn]+1) >= (size_t) MAX_COM_LENGTH) { + fprintf(stderr, "Comment text may not exceed %u bytes\n", + (unsigned int) MAX_COM_LENGTH); + exit(EXIT_FAILURE); + } strcpy(comment_arg, argv[argn]+1); for (;;) { comment_length = (unsigned int) strlen(comment_arg); @@ -462,9 +468,19 @@ main (int argc, char **argv) } if (++argn >= argc) ERREXIT("Missing ending quote mark"); + if (strlen(comment_arg) + 1 + strlen(argv[argn]) >= + (size_t) MAX_COM_LENGTH) { + fprintf(stderr, "Comment text may not exceed %u bytes\n", + (unsigned int) MAX_COM_LENGTH); + exit(EXIT_FAILURE); + } strcat(comment_arg, " "); strcat(comment_arg, argv[argn]); } + } else if (strlen(comment_arg) >= (size_t) MAX_COM_LENGTH) { + fprintf(stderr, "Comment text may not exceed %u bytes\n", + (unsigned int) MAX_COM_LENGTH); + exit(EXIT_FAILURE); } comment_length = (unsigned int) strlen(comment_arg); } else diff --git a/uppsrc/plugin/jpg/lib/wrppm.c b/uppsrc/plugin/jpg/lib/wrppm.c index cfd416022..1e56d9c50 100644 --- a/uppsrc/plugin/jpg/lib/wrppm.c +++ b/uppsrc/plugin/jpg/lib/wrppm.c @@ -2,6 +2,7 @@ * wrppm.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -40,11 +41,11 @@ #define BYTESPERSAMPLE 1 #define PPM_MAXVAL 255 #else -/* The word-per-sample format always puts the LSB first. */ +/* The word-per-sample format always puts the MSB first. */ #define PUTPPMSAMPLE(ptr,v) \ { register int val_ = v; \ - *ptr++ = (char) (val_ & 0xFF); \ *ptr++ = (char) ((val_ >> 8) & 0xFF); \ + *ptr++ = (char) (val_ & 0xFF); \ } #define BYTESPERSAMPLE 2 #define PPM_MAXVAL ((1<output_width > 32767 || cinfo->output_height > 32767) - ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width, + ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width, cinfo->output_height); if (cinfo->out_color_space != JCS_GRAYSCALE && diff --git a/uppsrc/plugin/jpg/lib/wrtarga.c b/uppsrc/plugin/jpg/lib/wrtarga.c index 65662738d..a3b7475cf 100644 --- a/uppsrc/plugin/jpg/lib/wrtarga.c +++ b/uppsrc/plugin/jpg/lib/wrtarga.c @@ -2,6 +2,7 @@ * wrtarga.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -73,7 +74,7 @@ write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors) targaheader[17] = 0x20; /* Top-down, non-interlaced */ if (cinfo->out_color_space == JCS_GRAYSCALE) { - targaheader[2] = 3; /* image type = uncompressed gray-scale */ + targaheader[2] = 3; /* image type = uncompressed grayscale */ targaheader[16] = 8; /* bits per pixel */ } else { /* must be RGB */ if (num_colors > 0) { @@ -247,7 +248,7 @@ jinit_write_targa (j_decompress_ptr cinfo) ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1); dest->pub.buffer_height = 1; - return (djpeg_dest_ptr) dest; + return &dest->pub; } #endif /* TARGA_SUPPORTED */ diff --git a/uppsrc/plugin/wincert/pdf.cpp b/uppsrc/plugin/wincert/pdf.cpp deleted file mode 100644 index 9d7129d0e..000000000 --- a/uppsrc/plugin/wincert/pdf.cpp +++ /dev/null @@ -1,363 +0,0 @@ -#include "wincert.h" - -class PDFInfo { -public: - struct Reference : Moveable { - Reference(const Nuller& = Null) : index(0) {} - Reference(int index_, word revision_) : index(index_), revision(revision_) {} - - String ToString() const; - - bool IsNullInstance() const { return index == 0; } - - int index; - word revision; - }; - - PDFInfo(); - - void Clear(); - - bool Open(const String& pdf_data); - -public: - bool SkipWhite(); - bool Check(const char *text); - int ScanInteger(); - Reference ScanReference(); - - bool ParseXRef(int startxref); - bool ParseRoot(); - bool ParsePageTree(Reference root); - - bool Seek(Reference ref); - -public: - enum { MAX_PDF_OBJECTS = 1000000 }; - - String pdf_data; - Vector objects; - Vector revisions; - Vector pages; - int startxref; - Reference trailer_root; - Reference trailer_info; - Reference page_tree; - String root_object; - const char *term; -}; - -String PDFInfo::Reference::ToString() const -{ - StringBuffer out; - out << index << ' ' << (int)revision << " R"; - return out; -} - -PDFInfo::PDFInfo() -{ - Clear(); -} - -void PDFInfo::Clear() -{ - pdf_data = Null; - objects.Clear(); - revisions.Clear(); - startxref = -1; - trailer_root = Null; - trailer_info = Null; - page_tree = Null; - root_object = Null; - term = NULL; -} - -bool PDFInfo::Open(const String& pdf_data_) -{ - Clear(); - pdf_data = pdf_data_; - const char *begin = pdf_data.Begin(); - term = pdf_data.End(); - while(term > begin && (byte)term[-1] <= ' ') - term--; - if(term - begin <= 5 || memcmp(term - 5, "%%EOF", 5)) - return false; - term -= 5; - while(term > begin && !IsDigit(*--term)) - ; - while(term > begin && IsDigit(term[-1])) - term--; - startxref = ScanInt(term); - if(!ParseXRef(startxref)) - return false; - if(!ParseRoot() || !ParsePageTree(page_tree)) - return false; - return true; -} - -bool PDFInfo::ParseXRef(int start) -{ - if(start < 0 || start >= pdf_data.GetLength() - 20) - return false; - term = pdf_data.GetIter(start); - if(!Check("xref")) - return false; - while(!Check("trailer")) { - if(!SkipWhite()) - return false; - int start = ScanInteger(); - int count = ScanInteger(); - if(start < 0 || count <= 0 || start + count > MAX_PDF_OBJECTS || !SkipWhite()) - return false; - int end = start + count; - if(objects.GetCount() < end) { - objects.SetCountR(end, -1); - revisions.SetCountR(end, 0xffffu); - } - for(int i = 0; i < count; i++) { - int offset = ScanInteger(); - int rev = ScanInteger(); - if(!SkipWhite()) - return false; - if(*term != 'f' && *term != 'n') - return false; - if(*term++ == 'f') { - offset = 0; - rev = 0xffffu; - } - if(objects[start + i] == -1) { - objects[start + i] = offset; - revisions[start + i] = rev; - } - } - } - if(!Check("<<")) - return false; - while(!Check(">>")) { - if(!SkipWhite()) - return false; - if(Check("/Size")) { - int sz = ScanInteger(); - if(sz < objects.GetCount()) - return false; - objects.SetCount(sz, -1); - revisions.SetCount(sz, 0xffffu); - } - else if(Check("/Root")) { - Reference root = ScanReference(); - if(IsNull(trailer_root)) - trailer_root = root; - } - else if(Check("/Info")) { - Reference info = ScanReference(); - if(IsNull(trailer_info)) - trailer_info = info; - } - else if(Check("/Prev")) { - int prev = ScanInteger(); - const char *store_term = term; - if(!ParseXRef(prev)) - return false; - term = store_term; - } - else { - while(*++term && *term != '/' && !(*term == '>' && term[1] == '>')) - ; - } - } - return true; -} - -bool PDFInfo::Seek(Reference r) -{ - if(r.index <= 0 || r.index >= objects.GetCount() || objects[r.index] == -1) - return false; - term = pdf_data.GetIter(objects[r.index]); - int index = ScanInteger(); - if(index != r.index) - return false; - int rev = ScanInteger(); - if(rev != r.revision) - return false; - if(!Check("obj") || !Check("<<")) - return false; - return true; -} - -bool PDFInfo::ParseRoot() -{ - if(!Seek(trailer_root)) - return false; - const char *begin = term; - while(*term) { - if(Check("/Pages")) { - page_tree = ScanReference(); - } - else - if(*term == '>' && term[1] == '>') - break; - else - term++; - } - root_object = String(begin, term); - return true; -} - -bool PDFInfo::ParsePageTree(Reference node) -{ - if(!Seek(node)) - return false; - if(!Check("/Type")) - return false; - if(Check("/Pages")) { - if(!Check("/Kids") || !Check("[")) - return false; - while(*term && !Check("]")) { - Reference kid = ScanReference(); - const char *stack = term; - if(!ParsePageTree(kid)) - return false; - term = stack; - } - return true; - } - else if(Check("/Page")) { - pages.Add(node); - return true; - } - else - return false; -} - -bool PDFInfo::SkipWhite() -{ - while(*term && (byte)*term <= ' ') - term++; - return !!*term; -} - -bool PDFInfo::Check(const char *text) -{ - if(!SkipWhite()) - return false; - int l = strlen(text); - if(memcmp(term, text, l)) - return false; - term += l; - return true; -} - -int PDFInfo::ScanInteger() -{ - if(!SkipWhite()) - return Null; - return ScanInt(term, &term); -} - -PDFInfo::Reference PDFInfo::ScanReference() -{ - int obj = ScanInteger(); - if(IsNull(obj)) - return Reference(); - int rev = ScanInteger(); - if(IsNull(rev)) - return Reference(); - if(SkipWhite() && *term == 'R') { - term++; - return Reference(obj, rev); - } - return Reference(); -} - -String CertSignPDF(PCCERT_CONTEXT cert_context, const String& pdf_data) -{ - PDFInfo pdfinfo; - if(!pdfinfo.Open(pdf_data) || pdfinfo.pages.IsEmpty()) - return String::GetVoid(); - StringBuffer out; - out.Cat(pdf_data); - int obj_index = pdfinfo.objects.GetCount(); - int sign_object = obj_index++; - int sign_dict = obj_index++; - int new_root = obj_index++; - int sign_off = out.GetLength(); - out << sign_object << " 0 obj\n" - "<>\n" - "endobj\n"; - int dict_off = out.GetLength(); - Time tm = GetSysTime(); - out << sign_dict << " 0 obj\n" - "<>>\n" - "endobj\n"; - int root_off = out.GetLength(); - out - << new_root << " 0 obj\n" - "<<" << pdfinfo.root_object - << "/AcroForm<>>>\n" - "endobj\n"; - int xref_offset = out.GetLength(); - out << "xref\n" - << sign_object << " 3\n" - << FormatIntDec(sign_off, 10, '0') << " 00000 n\r\n" - << FormatIntDec(dict_off, 10, '0') << " 00000 n\r\n" - << FormatIntDec(root_off, 10, '0') << " 00000 n\r\n" - "trailer\n" - "< <" << Uuid::Create() << "> ]\n" - "/Prev " << pdfinfo.startxref - << ">>\n" - "startxref\n" - << xref_offset - << "\n" - "%%EOF\n"; - int end_offset = out.GetLength(); - - String rcl_fmt = NFormat("%d %d %d ]", cert_offset, - post_offset, end_offset - post_offset); - ASSERT(rcl_fmt.GetLength() <= RCL_CONT); - memcpy(out.Begin() + br_offset, rcl_fmt, rcl_fmt.GetLength()); - - Vector sections; - Vector sizes; - sections.SetCount(2); - sizes.SetCount(2); - sections[0] = (const BYTE *)out.Begin(); - sizes[0] = cert_offset; - sections[1] = (const BYTE *)out.Begin() + post_offset; - sizes[1] = end_offset - post_offset; - int sig_len = 2 * CertSignLength(cert_context, sections, sizes); - if(sig_len <= cert_length) { - String signature = BinHexEncode(CertSign(cert_context, sections, sizes)); - ASSERT(signature.GetLength() <= cert_length); - memcpy(out.Begin() + cert_offset + 1, signature, signature.GetLength()); - return out; - } - cert_length = sig_len; - } -} diff --git a/uppsrc/plugin/wincert/util.cpp b/uppsrc/plugin/wincert/util.cpp deleted file mode 100644 index 997e8e6d3..000000000 --- a/uppsrc/plugin/wincert/util.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "wincert.h" - -String CertGetProperty(PCCERT_CONTEXT cert_context, DWORD propertyID) -{ - dword len = 0; - if(!CertGetCertificateContextProperty(cert_context, propertyID, NULL, &len)) - return String::GetVoid(); - Buffer prop(len); - if(!CertGetCertificateContextProperty(cert_context, propertyID, prop, &len)) - return String::GetVoid(); - return String(~prop, len); -} - -String CertGetName(PCCERT_CONTEXT cert_context, DWORD dwType, DWORD flags) -{ - dword len = CertGetNameString(cert_context, dwType, flags, NULL, NULL, NULL); - if(!len) - return String::GetVoid(); - Buffer name(len); - if(!(len = CertGetNameString(cert_context, dwType, flags, NULL, name, len))) - return String::GetVoid(); - return String(name, len - 1); -} - -String CertGetNameAttr(PCCERT_CONTEXT cert_context, const char *attrOID) -{ - dword len = CertGetNameString(cert_context, CERT_NAME_ATTR_TYPE, 0, (void *)attrOID, NULL, NULL); - if(!len) - return String::GetVoid(); - Buffer name(len); - if(!(len = CertGetNameString(cert_context, CERT_NAME_ATTR_TYPE, 0, (void *)attrOID, name, len))) - return String::GetVoid(); - return String(name, len - 1); -} - -/* -String CertGetHash(PCCERT_CONTEXT cert_context) -{ - dword hash_len = 0; - CertGetCertificateContextProperty(cert_context, CERT_HASH_PROP_ID, NULL, &hash_len); - Buffer hash(hash_len); - CertGetCertificateContextProperty(cert_context, CERT_HASH_PROP_ID, hash, &hash_len); - String cert_hash(~hash, hash_len); - return cert_hash; -} -*/ - -/* -String CertGetName(PCCERT_CONTEXT cert_context) -{ - dword type; - dword len = CertGetNameString(cert_context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, &type, NULL, NULL); - Buffer name(len); - CertGetNameString(cert_context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, &type, name, len); - String cert_name(name, len ? len - 1 : 0); - return cert_name; -} -*/ - -CertInfo CertGetInfo(PCCERT_CONTEXT cert_context) -{ - CertInfo out; - out.hash = CertGetProperty(cert_context, CERT_HASH_PROP_ID); - out.common_name = CertGetNameAttr(cert_context, szOID_COMMON_NAME); - out.organization = CertGetNameAttr(cert_context, szOID_ORGANIZATION_NAME); - out.organizational_unit = CertGetNameAttr(cert_context, szOID_ORGANIZATIONAL_UNIT_NAME); - out.email = CertGetNameAttr(cert_context, szOID_RSA_emailAddr); - out.issuer = CertGetName(cert_context, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG); - out.valid_from = Time(cert_context->pCertInfo->NotBefore); - out.valid_until = Time(cert_context->pCertInfo->NotAfter); -// out.valid_until = Cert - return out; -} - -static void _sCertSignSet(PCCERT_CONTEXT cert_context, CRYPT_SIGN_MESSAGE_PARA& sign) -{ - Zero(sign); - sign.cbSize = sizeof(sign); - sign.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; - sign.pSigningCert = cert_context; - sign.HashAlgorithm.pszObjId = szOID_RSA_SHA1RSA; - sign.HashAlgorithm.Parameters.cbData = NULL; - sign.cMsgCert = 1; - sign.rgpMsgCert = &sign.pSigningCert; - sign.cAuthAttr = 0; - sign.dwInnerContentType = 0; - sign.cMsgCrl = 0; - sign.cUnauthAttr = 0; - sign.dwFlags = 0; - sign.pvHashAuxInfo = NULL; - sign.rgAuthAttr = NULL; -} - -int CertSignLength(PCCERT_CONTEXT cert_context, Vector& sections, Vector& sizes) -{ - ASSERT(sections.GetCount() == sizes.GetCount()); - - CRYPT_SIGN_MESSAGE_PARA sign; - - _sCertSignSet(cert_context, sign); - - const BYTE **psect = sections.Begin(); - DWORD *psize = sizes.Begin(); - - DWORD out_size = 0; - if(!CryptSignMessage(&sign, TRUE, sections.GetCount(), psect, psize, NULL, &out_size)) - return 0; - return out_size; -} - -String CertSign(PCCERT_CONTEXT cert_context, Vector& sections, Vector& sizes) -{ - ASSERT(sections.GetCount() == sizes.GetCount()); - - CRYPT_SIGN_MESSAGE_PARA sign; - - _sCertSignSet(cert_context, sign); - - const BYTE **psect = sections.Begin(); - DWORD *psize = sizes.Begin(); - - DWORD out_size = 0; - if(!CryptSignMessage(&sign, TRUE, sections.GetCount(), psect, psize, NULL, &out_size)) - return String::GetVoid(); - Buffer out_data(out_size); - if(!CryptSignMessage(&sign, TRUE, sections.GetCount(), psect, psize, out_data, &out_size)) - return String::GetVoid(); - - return String(~out_data, out_size); -} - -String CertSign(PCCERT_CONTEXT context, const String& message) -{ - Vector sections; - Vector sizes; - sections.SetCount(1, (const BYTE *)message.Begin()); - sizes.SetCount(1, message.GetLength()); - return CertSign(context, sections, sizes); -} - -Array CertEnum(HCERTSTORE store) -{ - Array out_list; - - RLOG("store = " << FormatIntHex(store)); - - PCCERT_CONTEXT cert_context = NULL; - while(cert_context = CertEnumCertificatesInStore(store, cert_context)) { - out_list.Add() = CertGetInfo(cert_context); - } - - return out_list; -} - -PCCERT_CONTEXT CertFind(HCERTSTORE store, const String& hash) -{ - CRYPT_HASH_BLOB hash_blob; - hash_blob.pbData = (BYTE *)hash.Begin(); - hash_blob.cbData = hash.GetLength(); - - return CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - 0, CERT_FIND_HASH, &hash_blob, NULL); -} diff --git a/uppsrc/plugin/wincert/wincert.h b/uppsrc/plugin/wincert/wincert.h deleted file mode 100644 index ec9f9b9f3..000000000 --- a/uppsrc/plugin/wincert/wincert.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _wincert_wincert_h -#define _wincert_wincert_h - -#include -#include - -using namespace Upp; - -struct CertInfo { - String hash; - String common_name; - String organization; - String organizational_unit; - String email; - String issuer; - Time valid_from; - Time valid_until; -}; - -String CertGetProperty(PCCERT_CONTEXT cert_context, DWORD propertyID); -String CertGetName(PCCERT_CONTEXT cert_context, DWORD dwType, DWORD flags = 0); -String CertGetNameAttr(PCCERT_CONTEXT cert_context, const char *attrOID); -CertInfo CertGetInfo(PCCERT_CONTEXT cert_context); - -Array CertEnum(HCERTSTORE store); -PCCERT_CONTEXT CertFind(HCERTSTORE store, const String& hash); - -int CertSignLength(PCCERT_CONTEXT cert_context, Vector& sections, Vector& sizes); -String CertSign(PCCERT_CONTEXT cert_context, Vector& sections, Vector& sizes); -String CertSign(PCCERT_CONTEXT context, const String& message); - -String CertSignPDF(PCCERT_CONTEXT cert_context, const String& pdf_data); - -#endif diff --git a/uppsrc/plugin/wincert/wincert.upp b/uppsrc/plugin/wincert/wincert.upp deleted file mode 100644 index 44a073327..000000000 --- a/uppsrc/plugin/wincert/wincert.upp +++ /dev/null @@ -1,13 +0,0 @@ -description "Minimum Win32 certificate support and PDF digital signing\377"; - -uses - Web; - -library - Crypt32.lib; - -file - wincert.h, - util.cpp, - pdf.cpp; -