transupp.c 91 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373
  1. /*
  2. * transupp.c
  3. *
  4. * This file was part of the Independent JPEG Group's software:
  5. * Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding.
  6. * libjpeg-turbo Modifications:
  7. * Copyright (C) 2010, 2017, 2021-2022, D. R. Commander.
  8. * For conditions of distribution and use, see the accompanying README.ijg
  9. * file.
  10. *
  11. * This file contains image transformation routines and other utility code
  12. * used by the jpegtran sample application. These are NOT part of the core
  13. * JPEG library. But we keep these routines separate from jpegtran.c to
  14. * ease the task of maintaining jpegtran-like programs that have other user
  15. * interfaces.
  16. */
  17. /* Although this file really shouldn't have access to the library internals,
  18. * it's helpful to let it call jround_up() and jcopy_block_row().
  19. */
  20. #define JPEG_INTERNALS
  21. #include "jinclude.h"
  22. #include "jpeglib.h"
  23. #include "transupp.h" /* My own external interface */
  24. #include "jpegcomp.h"
  25. #include <ctype.h> /* to declare isdigit() */
  26. #if JPEG_LIB_VERSION >= 70
  27. #define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size
  28. #define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size
  29. #else
  30. #define dstinfo_min_DCT_h_scaled_size DCTSIZE
  31. #define dstinfo_min_DCT_v_scaled_size DCTSIZE
  32. #endif
  33. #if TRANSFORMS_SUPPORTED
  34. /*
  35. * Lossless image transformation routines. These routines work on DCT
  36. * coefficient arrays and thus do not require any lossy decompression
  37. * or recompression of the image.
  38. * Thanks to Guido Vollbeding for the initial design and code of this feature,
  39. * and to Ben Jackson for introducing the cropping feature.
  40. *
  41. * Horizontal flipping is done in-place, using a single top-to-bottom
  42. * pass through the virtual source array. It will thus be much the
  43. * fastest option for images larger than main memory.
  44. *
  45. * The other routines require a set of destination virtual arrays, so they
  46. * need twice as much memory as jpegtran normally does. The destination
  47. * arrays are always written in normal scan order (top to bottom) because
  48. * the virtual array manager expects this. The source arrays will be scanned
  49. * in the corresponding order, which means multiple passes through the source
  50. * arrays for most of the transforms. That could result in much thrashing
  51. * if the image is larger than main memory.
  52. *
  53. * If cropping or trimming is involved, the destination arrays may be smaller
  54. * than the source arrays. Note it is not possible to do horizontal flip
  55. * in-place when a nonzero Y crop offset is specified, since we'd have to move
  56. * data from one block row to another but the virtual array manager doesn't
  57. * guarantee we can touch more than one row at a time. So in that case,
  58. * we have to use a separate destination array.
  59. *
  60. * Some notes about the operating environment of the individual transform
  61. * routines:
  62. * 1. Both the source and destination virtual arrays are allocated from the
  63. * source JPEG object, and therefore should be manipulated by calling the
  64. * source's memory manager.
  65. * 2. The destination's component count should be used. It may be smaller
  66. * than the source's when forcing to grayscale.
  67. * 3. Likewise the destination's sampling factors should be used. When
  68. * forcing to grayscale the destination's sampling factors will be all 1,
  69. * and we may as well take that as the effective iMCU size.
  70. * 4. When "trim" is in effect, the destination's dimensions will be the
  71. * trimmed values but the source's will be untrimmed.
  72. * 5. When "crop" is in effect, the destination's dimensions will be the
  73. * cropped values but the source's will be uncropped. Each transform
  74. * routine is responsible for picking up source data starting at the
  75. * correct X and Y offset for the crop region. (The X and Y offsets
  76. * passed to the transform routines are measured in iMCU blocks of the
  77. * destination.)
  78. * 6. All the routines assume that the source and destination buffers are
  79. * padded out to a full iMCU boundary. This is true, although for the
  80. * source buffer it is an undocumented property of jdcoefct.c.
  81. */
  82. LOCAL(void)
  83. dequant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
  84. jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
  85. {
  86. JDIMENSION blk_x, blk_y;
  87. int offset_y, k;
  88. JQUANT_TBL *qtblptr;
  89. JBLOCKARRAY buffer;
  90. JBLOCKROW block;
  91. JCOEFPTR ptr;
  92. qtblptr = compptr->quant_table;
  93. for (blk_y = 0; blk_y < compptr->height_in_blocks;
  94. blk_y += compptr->v_samp_factor) {
  95. buffer = (*cinfo->mem->access_virt_barray)
  96. ((j_common_ptr)cinfo, coef_array, blk_y,
  97. (JDIMENSION)compptr->v_samp_factor, TRUE);
  98. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  99. block = buffer[offset_y];
  100. for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
  101. ptr = block[blk_x];
  102. for (k = 0; k < DCTSIZE2; k++)
  103. if (qtblptr->quantval[k] != qtblptr1->quantval[k])
  104. ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k];
  105. }
  106. }
  107. }
  108. }
  109. LOCAL(void)
  110. requant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
  111. jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
  112. {
  113. JDIMENSION blk_x, blk_y;
  114. int offset_y, k;
  115. JQUANT_TBL *qtblptr;
  116. JBLOCKARRAY buffer;
  117. JBLOCKROW block;
  118. JCOEFPTR ptr;
  119. JCOEF temp, qval;
  120. qtblptr = compptr->quant_table;
  121. for (blk_y = 0; blk_y < compptr->height_in_blocks;
  122. blk_y += compptr->v_samp_factor) {
  123. buffer = (*cinfo->mem->access_virt_barray)
  124. ((j_common_ptr)cinfo, coef_array, blk_y,
  125. (JDIMENSION)compptr->v_samp_factor, TRUE);
  126. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  127. block = buffer[offset_y];
  128. for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
  129. ptr = block[blk_x];
  130. for (k = 0; k < DCTSIZE2; k++) {
  131. temp = qtblptr->quantval[k];
  132. qval = qtblptr1->quantval[k];
  133. if (temp != qval) {
  134. temp *= ptr[k];
  135. /* The following quantization code is copied from jcdctmgr.c */
  136. #ifdef FAST_DIVIDE
  137. #define DIVIDE_BY(a, b) a /= b
  138. #else
  139. #define DIVIDE_BY(a, b) if (a >= b) a /= b; else a = 0
  140. #endif
  141. if (temp < 0) {
  142. temp = -temp;
  143. temp += qval >> 1; /* for rounding */
  144. DIVIDE_BY(temp, qval);
  145. temp = -temp;
  146. } else {
  147. temp += qval >> 1; /* for rounding */
  148. DIVIDE_BY(temp, qval);
  149. }
  150. ptr[k] = temp;
  151. }
  152. }
  153. }
  154. }
  155. }
  156. }
  157. /*
  158. * Calculate largest common denominator using Euclid's algorithm.
  159. */
  160. LOCAL(JCOEF)
  161. largest_common_denominator(JCOEF a, JCOEF b)
  162. {
  163. JCOEF c;
  164. do {
  165. c = a % b;
  166. a = b;
  167. b = c;
  168. } while (c);
  169. return a;
  170. }
  171. LOCAL(void)
  172. adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays,
  173. j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
  174. boolean trim, j_compress_ptr dstinfo)
  175. {
  176. jpeg_component_info *compptr1, *compptr2;
  177. JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3;
  178. int ci, k;
  179. for (ci = 0; ci < dstinfo->num_components && ci < dropinfo->num_components;
  180. ci++) {
  181. compptr1 = srcinfo->comp_info + ci;
  182. compptr2 = dropinfo->comp_info + ci;
  183. qtblptr1 = compptr1->quant_table;
  184. qtblptr2 = compptr2->quant_table;
  185. for (k = 0; k < DCTSIZE2; k++) {
  186. if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) {
  187. if (trim)
  188. requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1);
  189. else {
  190. qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no];
  191. for (k = 0; k < DCTSIZE2; k++)
  192. if (qtblptr1->quantval[k] != qtblptr2->quantval[k])
  193. qtblptr3->quantval[k] =
  194. largest_common_denominator(qtblptr1->quantval[k],
  195. qtblptr2->quantval[k]);
  196. dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3);
  197. dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3);
  198. }
  199. break;
  200. }
  201. }
  202. }
  203. }
  204. LOCAL(void)
  205. do_drop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  206. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  207. jvirt_barray_ptr *src_coef_arrays,
  208. j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
  209. JDIMENSION drop_width, JDIMENSION drop_height)
  210. /* Drop (insert) the contents of another image into the source image. If the
  211. * number of components in the drop image is smaller than the number of
  212. * components in the destination image, then we fill in the remaining
  213. * components with zero. This allows for dropping the contents of grayscale
  214. * images into (arbitrarily sampled) color images.
  215. */
  216. {
  217. JDIMENSION comp_width, comp_height;
  218. JDIMENSION blk_y, x_drop_blocks, y_drop_blocks;
  219. int ci, offset_y;
  220. JBLOCKARRAY src_buffer, dst_buffer;
  221. jpeg_component_info *compptr;
  222. for (ci = 0; ci < dstinfo->num_components; ci++) {
  223. compptr = dstinfo->comp_info + ci;
  224. comp_width = drop_width * compptr->h_samp_factor;
  225. comp_height = drop_height * compptr->v_samp_factor;
  226. x_drop_blocks = x_crop_offset * compptr->h_samp_factor;
  227. y_drop_blocks = y_crop_offset * compptr->v_samp_factor;
  228. for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) {
  229. dst_buffer = (*srcinfo->mem->access_virt_barray)
  230. ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks,
  231. (JDIMENSION)compptr->v_samp_factor, TRUE);
  232. if (ci < dropinfo->num_components) {
  233. src_buffer = (*dropinfo->mem->access_virt_barray)
  234. ((j_common_ptr)dropinfo, drop_coef_arrays[ci], blk_y,
  235. (JDIMENSION)compptr->v_samp_factor, FALSE);
  236. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  237. jcopy_block_row(src_buffer[offset_y],
  238. dst_buffer[offset_y] + x_drop_blocks, comp_width);
  239. }
  240. } else {
  241. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  242. memset(dst_buffer[offset_y] + x_drop_blocks, 0,
  243. comp_width * sizeof(JBLOCK));
  244. }
  245. }
  246. }
  247. }
  248. }
  249. LOCAL(void)
  250. do_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  251. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  252. jvirt_barray_ptr *src_coef_arrays,
  253. jvirt_barray_ptr *dst_coef_arrays)
  254. /* Crop. This is only used when no rotate/flip is requested with the crop. */
  255. {
  256. JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
  257. int ci, offset_y;
  258. JBLOCKARRAY src_buffer, dst_buffer;
  259. jpeg_component_info *compptr;
  260. /* We simply have to copy the right amount of data (the destination's
  261. * image size) starting at the given X and Y offsets in the source.
  262. */
  263. for (ci = 0; ci < dstinfo->num_components; ci++) {
  264. compptr = dstinfo->comp_info + ci;
  265. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  266. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  267. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  268. dst_blk_y += compptr->v_samp_factor) {
  269. dst_buffer = (*srcinfo->mem->access_virt_barray)
  270. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  271. (JDIMENSION)compptr->v_samp_factor, TRUE);
  272. src_buffer = (*srcinfo->mem->access_virt_barray)
  273. ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
  274. (JDIMENSION)compptr->v_samp_factor, FALSE);
  275. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  276. jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
  277. dst_buffer[offset_y], compptr->width_in_blocks);
  278. }
  279. }
  280. }
  281. }
  282. LOCAL(void)
  283. do_crop_ext_zero(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  284. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  285. jvirt_barray_ptr *src_coef_arrays,
  286. jvirt_barray_ptr *dst_coef_arrays)
  287. /* Crop. This is only used when no rotate/flip is requested with the crop.
  288. * Extension: If the destination size is larger than the source, we fill in the
  289. * expanded region with zero (neutral gray). Note that we also have to zero
  290. * partial iMCUs at the right and bottom edge of the source image area in this
  291. * case.
  292. */
  293. {
  294. JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
  295. JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
  296. int ci, offset_y;
  297. JBLOCKARRAY src_buffer, dst_buffer;
  298. jpeg_component_info *compptr;
  299. MCU_cols = srcinfo->output_width /
  300. (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
  301. MCU_rows = srcinfo->output_height /
  302. (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
  303. for (ci = 0; ci < dstinfo->num_components; ci++) {
  304. compptr = dstinfo->comp_info + ci;
  305. comp_width = MCU_cols * compptr->h_samp_factor;
  306. comp_height = MCU_rows * compptr->v_samp_factor;
  307. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  308. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  309. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  310. dst_blk_y += compptr->v_samp_factor) {
  311. dst_buffer = (*srcinfo->mem->access_virt_barray)
  312. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  313. (JDIMENSION)compptr->v_samp_factor, TRUE);
  314. if (dstinfo->_jpeg_height > srcinfo->output_height) {
  315. if (dst_blk_y < y_crop_blocks ||
  316. dst_blk_y >= y_crop_blocks + comp_height) {
  317. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  318. memset(dst_buffer[offset_y], 0,
  319. compptr->width_in_blocks * sizeof(JBLOCK));
  320. }
  321. continue;
  322. }
  323. src_buffer = (*srcinfo->mem->access_virt_barray)
  324. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  325. dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
  326. FALSE);
  327. } else {
  328. src_buffer = (*srcinfo->mem->access_virt_barray)
  329. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  330. dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
  331. FALSE);
  332. }
  333. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  334. if (dstinfo->_jpeg_width > srcinfo->output_width) {
  335. if (x_crop_blocks > 0) {
  336. memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK));
  337. }
  338. jcopy_block_row(src_buffer[offset_y],
  339. dst_buffer[offset_y] + x_crop_blocks, comp_width);
  340. if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
  341. memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0,
  342. (compptr->width_in_blocks - x_crop_blocks - comp_width) *
  343. sizeof(JBLOCK));
  344. }
  345. } else {
  346. jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
  347. dst_buffer[offset_y], compptr->width_in_blocks);
  348. }
  349. }
  350. }
  351. }
  352. }
  353. LOCAL(void)
  354. do_crop_ext_flat(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  355. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  356. jvirt_barray_ptr *src_coef_arrays,
  357. jvirt_barray_ptr *dst_coef_arrays)
  358. /* Crop. This is only used when no rotate/flip is requested with the crop.
  359. * Extension: The destination width is larger than the source, and we fill in
  360. * the expanded region with the DC coefficient of the adjacent block. Note
  361. * that we also have to fill partial iMCUs at the right and bottom edge of the
  362. * source image area in this case.
  363. */
  364. {
  365. JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
  366. JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
  367. int ci, offset_y;
  368. JCOEF dc;
  369. JBLOCKARRAY src_buffer, dst_buffer;
  370. jpeg_component_info *compptr;
  371. MCU_cols = srcinfo->output_width /
  372. (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
  373. MCU_rows = srcinfo->output_height /
  374. (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
  375. for (ci = 0; ci < dstinfo->num_components; ci++) {
  376. compptr = dstinfo->comp_info + ci;
  377. comp_width = MCU_cols * compptr->h_samp_factor;
  378. comp_height = MCU_rows * compptr->v_samp_factor;
  379. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  380. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  381. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  382. dst_blk_y += compptr->v_samp_factor) {
  383. dst_buffer = (*srcinfo->mem->access_virt_barray)
  384. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  385. (JDIMENSION)compptr->v_samp_factor, TRUE);
  386. if (dstinfo->_jpeg_height > srcinfo->output_height) {
  387. if (dst_blk_y < y_crop_blocks ||
  388. dst_blk_y >= y_crop_blocks + comp_height) {
  389. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  390. memset(dst_buffer[offset_y], 0,
  391. compptr->width_in_blocks * sizeof(JBLOCK));
  392. }
  393. continue;
  394. }
  395. src_buffer = (*srcinfo->mem->access_virt_barray)
  396. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  397. dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
  398. FALSE);
  399. } else {
  400. src_buffer = (*srcinfo->mem->access_virt_barray)
  401. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  402. dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
  403. FALSE);
  404. }
  405. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  406. if (x_crop_blocks > 0) {
  407. memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK));
  408. dc = src_buffer[offset_y][0][0];
  409. for (dst_blk_x = 0; dst_blk_x < x_crop_blocks; dst_blk_x++) {
  410. dst_buffer[offset_y][dst_blk_x][0] = dc;
  411. }
  412. }
  413. jcopy_block_row(src_buffer[offset_y],
  414. dst_buffer[offset_y] + x_crop_blocks, comp_width);
  415. if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
  416. memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0,
  417. (compptr->width_in_blocks - x_crop_blocks - comp_width) *
  418. sizeof(JBLOCK));
  419. dc = src_buffer[offset_y][comp_width - 1][0];
  420. for (dst_blk_x = x_crop_blocks + comp_width;
  421. dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
  422. dst_buffer[offset_y][dst_blk_x][0] = dc;
  423. }
  424. }
  425. }
  426. }
  427. }
  428. }
  429. LOCAL(void)
  430. do_crop_ext_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  431. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  432. jvirt_barray_ptr *src_coef_arrays,
  433. jvirt_barray_ptr *dst_coef_arrays)
  434. /* Crop. This is only used when no rotate/flip is requested with the crop.
  435. * Extension: The destination width is larger than the source, and we fill in
  436. * the expanded region with repeated reflections of the source image. Note
  437. * that we also have to fill partial iMCUs at the right and bottom edge of the
  438. * source image area in this case.
  439. */
  440. {
  441. JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, src_blk_x;
  442. JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
  443. int ci, k, offset_y;
  444. JBLOCKARRAY src_buffer, dst_buffer;
  445. JBLOCKROW src_row_ptr, dst_row_ptr;
  446. JCOEFPTR src_ptr, dst_ptr;
  447. jpeg_component_info *compptr;
  448. MCU_cols = srcinfo->output_width /
  449. (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
  450. MCU_rows = srcinfo->output_height /
  451. (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
  452. for (ci = 0; ci < dstinfo->num_components; ci++) {
  453. compptr = dstinfo->comp_info + ci;
  454. comp_width = MCU_cols * compptr->h_samp_factor;
  455. comp_height = MCU_rows * compptr->v_samp_factor;
  456. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  457. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  458. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  459. dst_blk_y += compptr->v_samp_factor) {
  460. dst_buffer = (*srcinfo->mem->access_virt_barray)
  461. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  462. (JDIMENSION)compptr->v_samp_factor, TRUE);
  463. if (dstinfo->_jpeg_height > srcinfo->output_height) {
  464. if (dst_blk_y < y_crop_blocks ||
  465. dst_blk_y >= y_crop_blocks + comp_height) {
  466. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  467. memset(dst_buffer[offset_y], 0,
  468. compptr->width_in_blocks * sizeof(JBLOCK));
  469. }
  470. continue;
  471. }
  472. src_buffer = (*srcinfo->mem->access_virt_barray)
  473. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  474. dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
  475. FALSE);
  476. } else {
  477. src_buffer = (*srcinfo->mem->access_virt_barray)
  478. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  479. dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
  480. FALSE);
  481. }
  482. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  483. /* Copy source region */
  484. jcopy_block_row(src_buffer[offset_y],
  485. dst_buffer[offset_y] + x_crop_blocks, comp_width);
  486. if (x_crop_blocks > 0) {
  487. /* Reflect to left */
  488. dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks;
  489. for (dst_blk_x = x_crop_blocks; dst_blk_x > 0;) {
  490. src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
  491. for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
  492. src_blk_x--, dst_blk_x--) {
  493. dst_ptr = *(--dst_row_ptr); /* destination goes left */
  494. src_ptr = *src_row_ptr++; /* source goes right */
  495. /* This unrolled loop doesn't need to know which row it's on. */
  496. for (k = 0; k < DCTSIZE2; k += 2) {
  497. *dst_ptr++ = *src_ptr++; /* copy even column */
  498. *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
  499. change */
  500. }
  501. }
  502. }
  503. }
  504. if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
  505. /* Reflect to right */
  506. dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks + comp_width;
  507. for (dst_blk_x = compptr->width_in_blocks - x_crop_blocks - comp_width;
  508. dst_blk_x > 0;) {
  509. src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
  510. for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
  511. src_blk_x--, dst_blk_x--) {
  512. dst_ptr = *dst_row_ptr++; /* destination goes right */
  513. src_ptr = *(--src_row_ptr); /* source goes left */
  514. /* This unrolled loop doesn't need to know which row it's on. */
  515. for (k = 0; k < DCTSIZE2; k += 2) {
  516. *dst_ptr++ = *src_ptr++; /* copy even column */
  517. *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
  518. change */
  519. }
  520. }
  521. }
  522. }
  523. }
  524. }
  525. }
  526. }
  527. LOCAL(void)
  528. do_wipe(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  529. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  530. jvirt_barray_ptr *src_coef_arrays,
  531. JDIMENSION drop_width, JDIMENSION drop_height)
  532. /* Wipe - discard image contents of specified region and fill with zero
  533. * (neutral gray)
  534. */
  535. {
  536. JDIMENSION x_wipe_blocks, wipe_width;
  537. JDIMENSION y_wipe_blocks, wipe_bottom;
  538. int ci, offset_y;
  539. JBLOCKARRAY buffer;
  540. jpeg_component_info *compptr;
  541. for (ci = 0; ci < dstinfo->num_components; ci++) {
  542. compptr = dstinfo->comp_info + ci;
  543. x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
  544. wipe_width = drop_width * compptr->h_samp_factor;
  545. y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
  546. wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
  547. for (; y_wipe_blocks < wipe_bottom;
  548. y_wipe_blocks += compptr->v_samp_factor) {
  549. buffer = (*srcinfo->mem->access_virt_barray)
  550. ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
  551. (JDIMENSION)compptr->v_samp_factor, TRUE);
  552. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  553. memset(buffer[offset_y] + x_wipe_blocks, 0,
  554. wipe_width * sizeof(JBLOCK));
  555. }
  556. }
  557. }
  558. }
  559. LOCAL(void)
  560. do_flatten(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  561. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  562. jvirt_barray_ptr *src_coef_arrays,
  563. JDIMENSION drop_width, JDIMENSION drop_height)
  564. /* Flatten - discard image contents of specified region, similarly to wipe,
  565. * but fill with the average of adjacent blocks instead of zero.
  566. */
  567. {
  568. JDIMENSION x_wipe_blocks, wipe_width, wipe_right;
  569. JDIMENSION y_wipe_blocks, wipe_bottom, blk_x;
  570. int ci, offset_y, dc_left_value, dc_right_value, average;
  571. JBLOCKARRAY buffer;
  572. jpeg_component_info *compptr;
  573. for (ci = 0; ci < dstinfo->num_components; ci++) {
  574. compptr = dstinfo->comp_info + ci;
  575. x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
  576. wipe_width = drop_width * compptr->h_samp_factor;
  577. wipe_right = wipe_width + x_wipe_blocks;
  578. y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
  579. wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
  580. for (; y_wipe_blocks < wipe_bottom;
  581. y_wipe_blocks += compptr->v_samp_factor) {
  582. buffer = (*srcinfo->mem->access_virt_barray)
  583. ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
  584. (JDIMENSION)compptr->v_samp_factor, TRUE);
  585. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  586. memset(buffer[offset_y] + x_wipe_blocks, 0,
  587. wipe_width * sizeof(JBLOCK));
  588. if (x_wipe_blocks > 0) {
  589. dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0];
  590. if (wipe_right < compptr->width_in_blocks) {
  591. dc_right_value = buffer[offset_y][wipe_right][0];
  592. average = (dc_left_value + dc_right_value) >> 1;
  593. } else {
  594. average = dc_left_value;
  595. }
  596. } else if (wipe_right < compptr->width_in_blocks) {
  597. average = buffer[offset_y][wipe_right][0];
  598. } else continue;
  599. for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) {
  600. buffer[offset_y][blk_x][0] = (JCOEF)average;
  601. }
  602. }
  603. }
  604. }
  605. }
  606. LOCAL(void)
  607. do_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  608. JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays,
  609. JDIMENSION drop_width, JDIMENSION drop_height)
  610. /* Reflect - discard image contents of specified region, similarly to wipe,
  611. * but fill with repeated reflections of the outside region instead of zero.
  612. * NB: y_crop_offset is assumed to be zero.
  613. */
  614. {
  615. JDIMENSION x_wipe_blocks, wipe_width;
  616. JDIMENSION y_wipe_blocks, wipe_bottom;
  617. JDIMENSION src_blk_x, dst_blk_x;
  618. int ci, k, offset_y;
  619. JBLOCKARRAY buffer;
  620. JBLOCKROW src_row_ptr, dst_row_ptr;
  621. JCOEFPTR src_ptr, dst_ptr;
  622. jpeg_component_info *compptr;
  623. for (ci = 0; ci < dstinfo->num_components; ci++) {
  624. compptr = dstinfo->comp_info + ci;
  625. x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
  626. wipe_width = drop_width * compptr->h_samp_factor;
  627. wipe_bottom = drop_height * compptr->v_samp_factor;
  628. for (y_wipe_blocks = 0; y_wipe_blocks < wipe_bottom;
  629. y_wipe_blocks += compptr->v_samp_factor) {
  630. buffer = (*srcinfo->mem->access_virt_barray)
  631. ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
  632. (JDIMENSION)compptr->v_samp_factor, TRUE);
  633. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  634. if (x_wipe_blocks > 0) {
  635. /* Reflect from left */
  636. dst_row_ptr = buffer[offset_y] + x_wipe_blocks;
  637. for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
  638. src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
  639. for (src_blk_x = x_wipe_blocks;
  640. src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
  641. dst_ptr = *dst_row_ptr++; /* destination goes right */
  642. src_ptr = *(--src_row_ptr); /* source goes left */
  643. /* this unrolled loop doesn't need to know which row it's on... */
  644. for (k = 0; k < DCTSIZE2; k += 2) {
  645. *dst_ptr++ = *src_ptr++; /* copy even column */
  646. *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
  647. }
  648. }
  649. }
  650. } else if (compptr->width_in_blocks > x_wipe_blocks + wipe_width) {
  651. /* Reflect from right */
  652. dst_row_ptr = buffer[offset_y] + x_wipe_blocks + wipe_width;
  653. for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
  654. src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
  655. src_blk_x = compptr->width_in_blocks - x_wipe_blocks - wipe_width;
  656. for (; src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
  657. dst_ptr = *(--dst_row_ptr); /* destination goes left */
  658. src_ptr = *src_row_ptr++; /* source goes right */
  659. /* this unrolled loop doesn't need to know which row it's on... */
  660. for (k = 0; k < DCTSIZE2; k += 2) {
  661. *dst_ptr++ = *src_ptr++; /* copy even column */
  662. *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
  663. }
  664. }
  665. }
  666. } else {
  667. memset(buffer[offset_y] + x_wipe_blocks, 0,
  668. wipe_width * sizeof(JBLOCK));
  669. }
  670. }
  671. }
  672. }
  673. }
  674. LOCAL(void)
  675. do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  676. JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
  677. /* Horizontal flip; done in-place, so no separate dest array is required.
  678. * NB: this only works when y_crop_offset is zero.
  679. */
  680. {
  681. JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
  682. int ci, k, offset_y;
  683. JBLOCKARRAY buffer;
  684. JCOEFPTR ptr1, ptr2;
  685. JCOEF temp1, temp2;
  686. jpeg_component_info *compptr;
  687. /* Horizontal mirroring of DCT blocks is accomplished by swapping
  688. * pairs of blocks in-place. Within a DCT block, we perform horizontal
  689. * mirroring by changing the signs of odd-numbered columns.
  690. * Partial iMCUs at the right edge are left untouched.
  691. */
  692. MCU_cols = srcinfo->output_width /
  693. (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
  694. for (ci = 0; ci < dstinfo->num_components; ci++) {
  695. compptr = dstinfo->comp_info + ci;
  696. comp_width = MCU_cols * compptr->h_samp_factor;
  697. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  698. for (blk_y = 0; blk_y < compptr->height_in_blocks;
  699. blk_y += compptr->v_samp_factor) {
  700. buffer = (*srcinfo->mem->access_virt_barray)
  701. ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y,
  702. (JDIMENSION)compptr->v_samp_factor, TRUE);
  703. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  704. /* Do the mirroring */
  705. for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
  706. ptr1 = buffer[offset_y][blk_x];
  707. ptr2 = buffer[offset_y][comp_width - blk_x - 1];
  708. /* this unrolled loop doesn't need to know which row it's on... */
  709. for (k = 0; k < DCTSIZE2; k += 2) {
  710. temp1 = *ptr1; /* swap even column */
  711. temp2 = *ptr2;
  712. *ptr1++ = temp2;
  713. *ptr2++ = temp1;
  714. temp1 = *ptr1; /* swap odd column with sign change */
  715. temp2 = *ptr2;
  716. *ptr1++ = -temp2;
  717. *ptr2++ = -temp1;
  718. }
  719. }
  720. if (x_crop_blocks > 0) {
  721. /* Now left-justify the portion of the data to be kept.
  722. * We can't use a single jcopy_block_row() call because that routine
  723. * depends on memcpy(), whose behavior is unspecified for overlapping
  724. * source and destination areas. Sigh.
  725. */
  726. for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
  727. jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
  728. buffer[offset_y] + blk_x, (JDIMENSION)1);
  729. }
  730. }
  731. }
  732. }
  733. }
  734. }
  735. LOCAL(void)
  736. do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  737. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  738. jvirt_barray_ptr *src_coef_arrays,
  739. jvirt_barray_ptr *dst_coef_arrays)
  740. /* Horizontal flip in general cropping case */
  741. {
  742. JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
  743. JDIMENSION x_crop_blocks, y_crop_blocks;
  744. int ci, k, offset_y;
  745. JBLOCKARRAY src_buffer, dst_buffer;
  746. JBLOCKROW src_row_ptr, dst_row_ptr;
  747. JCOEFPTR src_ptr, dst_ptr;
  748. jpeg_component_info *compptr;
  749. /* Here we must output into a separate array because we can't touch
  750. * different rows of a single virtual array simultaneously. Otherwise,
  751. * this is essentially the same as the routine above.
  752. */
  753. MCU_cols = srcinfo->output_width /
  754. (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
  755. for (ci = 0; ci < dstinfo->num_components; ci++) {
  756. compptr = dstinfo->comp_info + ci;
  757. comp_width = MCU_cols * compptr->h_samp_factor;
  758. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  759. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  760. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  761. dst_blk_y += compptr->v_samp_factor) {
  762. dst_buffer = (*srcinfo->mem->access_virt_barray)
  763. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  764. (JDIMENSION)compptr->v_samp_factor, TRUE);
  765. src_buffer = (*srcinfo->mem->access_virt_barray)
  766. ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
  767. (JDIMENSION)compptr->v_samp_factor, FALSE);
  768. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  769. dst_row_ptr = dst_buffer[offset_y];
  770. src_row_ptr = src_buffer[offset_y];
  771. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  772. dst_blk_x++) {
  773. if (x_crop_blocks + dst_blk_x < comp_width) {
  774. /* Do the mirrorable blocks */
  775. dst_ptr = dst_row_ptr[dst_blk_x];
  776. src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
  777. /* this unrolled loop doesn't need to know which row it's on... */
  778. for (k = 0; k < DCTSIZE2; k += 2) {
  779. *dst_ptr++ = *src_ptr++; /* copy even column */
  780. *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
  781. change */
  782. }
  783. } else {
  784. /* Copy last partial block(s) verbatim */
  785. jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
  786. dst_row_ptr + dst_blk_x, (JDIMENSION)1);
  787. }
  788. }
  789. }
  790. }
  791. }
  792. }
  793. LOCAL(void)
  794. do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  795. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  796. jvirt_barray_ptr *src_coef_arrays,
  797. jvirt_barray_ptr *dst_coef_arrays)
  798. /* Vertical flip */
  799. {
  800. JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
  801. JDIMENSION x_crop_blocks, y_crop_blocks;
  802. int ci, i, j, offset_y;
  803. JBLOCKARRAY src_buffer, dst_buffer;
  804. JBLOCKROW src_row_ptr, dst_row_ptr;
  805. JCOEFPTR src_ptr, dst_ptr;
  806. jpeg_component_info *compptr;
  807. /* We output into a separate array because we can't touch different
  808. * rows of the source virtual array simultaneously. Otherwise, this
  809. * is a pretty straightforward analog of horizontal flip.
  810. * Within a DCT block, vertical mirroring is done by changing the signs
  811. * of odd-numbered rows.
  812. * Partial iMCUs at the bottom edge are copied verbatim.
  813. */
  814. MCU_rows = srcinfo->output_height /
  815. (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
  816. for (ci = 0; ci < dstinfo->num_components; ci++) {
  817. compptr = dstinfo->comp_info + ci;
  818. comp_height = MCU_rows * compptr->v_samp_factor;
  819. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  820. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  821. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  822. dst_blk_y += compptr->v_samp_factor) {
  823. dst_buffer = (*srcinfo->mem->access_virt_barray)
  824. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  825. (JDIMENSION)compptr->v_samp_factor, TRUE);
  826. if (y_crop_blocks + dst_blk_y < comp_height) {
  827. /* Row is within the mirrorable area. */
  828. src_buffer = (*srcinfo->mem->access_virt_barray)
  829. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  830. comp_height - y_crop_blocks - dst_blk_y -
  831. (JDIMENSION)compptr->v_samp_factor,
  832. (JDIMENSION)compptr->v_samp_factor, FALSE);
  833. } else {
  834. /* Bottom-edge blocks will be copied verbatim. */
  835. src_buffer = (*srcinfo->mem->access_virt_barray)
  836. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  837. dst_blk_y + y_crop_blocks,
  838. (JDIMENSION)compptr->v_samp_factor, FALSE);
  839. }
  840. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  841. if (y_crop_blocks + dst_blk_y < comp_height) {
  842. /* Row is within the mirrorable area. */
  843. dst_row_ptr = dst_buffer[offset_y];
  844. src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
  845. src_row_ptr += x_crop_blocks;
  846. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  847. dst_blk_x++) {
  848. dst_ptr = dst_row_ptr[dst_blk_x];
  849. src_ptr = src_row_ptr[dst_blk_x];
  850. for (i = 0; i < DCTSIZE; i += 2) {
  851. /* copy even row */
  852. for (j = 0; j < DCTSIZE; j++)
  853. *dst_ptr++ = *src_ptr++;
  854. /* copy odd row with sign change */
  855. for (j = 0; j < DCTSIZE; j++)
  856. *dst_ptr++ = -(*src_ptr++);
  857. }
  858. }
  859. } else {
  860. /* Just copy row verbatim. */
  861. jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
  862. dst_buffer[offset_y], compptr->width_in_blocks);
  863. }
  864. }
  865. }
  866. }
  867. }
  868. LOCAL(void)
  869. do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  870. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  871. jvirt_barray_ptr *src_coef_arrays,
  872. jvirt_barray_ptr *dst_coef_arrays)
  873. /* Transpose source into destination */
  874. {
  875. JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
  876. int ci, i, j, offset_x, offset_y;
  877. JBLOCKARRAY src_buffer, dst_buffer;
  878. JCOEFPTR src_ptr, dst_ptr;
  879. jpeg_component_info *compptr;
  880. /* Transposing pixels within a block just requires transposing the
  881. * DCT coefficients.
  882. * Partial iMCUs at the edges require no special treatment; we simply
  883. * process all the available DCT blocks for every component.
  884. */
  885. for (ci = 0; ci < dstinfo->num_components; ci++) {
  886. compptr = dstinfo->comp_info + ci;
  887. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  888. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  889. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  890. dst_blk_y += compptr->v_samp_factor) {
  891. dst_buffer = (*srcinfo->mem->access_virt_barray)
  892. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  893. (JDIMENSION)compptr->v_samp_factor, TRUE);
  894. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  895. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  896. dst_blk_x += compptr->h_samp_factor) {
  897. src_buffer = (*srcinfo->mem->access_virt_barray)
  898. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  899. dst_blk_x + x_crop_blocks,
  900. (JDIMENSION)compptr->h_samp_factor, FALSE);
  901. for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
  902. dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  903. src_ptr =
  904. src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
  905. for (i = 0; i < DCTSIZE; i++)
  906. for (j = 0; j < DCTSIZE; j++)
  907. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  908. }
  909. }
  910. }
  911. }
  912. }
  913. }
  914. LOCAL(void)
  915. do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  916. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  917. jvirt_barray_ptr *src_coef_arrays,
  918. jvirt_barray_ptr *dst_coef_arrays)
  919. /* 90 degree rotation is equivalent to
  920. * 1. Transposing the image;
  921. * 2. Horizontal mirroring.
  922. * These two steps are merged into a single processing routine.
  923. */
  924. {
  925. JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
  926. JDIMENSION x_crop_blocks, y_crop_blocks;
  927. int ci, i, j, offset_x, offset_y;
  928. JBLOCKARRAY src_buffer, dst_buffer;
  929. JCOEFPTR src_ptr, dst_ptr;
  930. jpeg_component_info *compptr;
  931. /* Because of the horizontal mirror step, we can't process partial iMCUs
  932. * at the (output) right edge properly. They just get transposed and
  933. * not mirrored.
  934. */
  935. MCU_cols = srcinfo->output_height /
  936. (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
  937. for (ci = 0; ci < dstinfo->num_components; ci++) {
  938. compptr = dstinfo->comp_info + ci;
  939. comp_width = MCU_cols * compptr->h_samp_factor;
  940. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  941. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  942. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  943. dst_blk_y += compptr->v_samp_factor) {
  944. dst_buffer = (*srcinfo->mem->access_virt_barray)
  945. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  946. (JDIMENSION)compptr->v_samp_factor, TRUE);
  947. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  948. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  949. dst_blk_x += compptr->h_samp_factor) {
  950. if (x_crop_blocks + dst_blk_x < comp_width) {
  951. /* Block is within the mirrorable area. */
  952. src_buffer = (*srcinfo->mem->access_virt_barray)
  953. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  954. comp_width - x_crop_blocks - dst_blk_x -
  955. (JDIMENSION)compptr->h_samp_factor,
  956. (JDIMENSION)compptr->h_samp_factor, FALSE);
  957. } else {
  958. /* Edge blocks are transposed but not mirrored. */
  959. src_buffer = (*srcinfo->mem->access_virt_barray)
  960. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  961. dst_blk_x + x_crop_blocks,
  962. (JDIMENSION)compptr->h_samp_factor, FALSE);
  963. }
  964. for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
  965. dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  966. if (x_crop_blocks + dst_blk_x < comp_width) {
  967. /* Block is within the mirrorable area. */
  968. src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
  969. [dst_blk_y + offset_y + y_crop_blocks];
  970. for (i = 0; i < DCTSIZE; i++) {
  971. for (j = 0; j < DCTSIZE; j++)
  972. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  973. i++;
  974. for (j = 0; j < DCTSIZE; j++)
  975. dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
  976. }
  977. } else {
  978. /* Edge blocks are transposed but not mirrored. */
  979. src_ptr = src_buffer[offset_x]
  980. [dst_blk_y + offset_y + y_crop_blocks];
  981. for (i = 0; i < DCTSIZE; i++)
  982. for (j = 0; j < DCTSIZE; j++)
  983. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  984. }
  985. }
  986. }
  987. }
  988. }
  989. }
  990. }
  991. LOCAL(void)
  992. do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  993. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  994. jvirt_barray_ptr *src_coef_arrays,
  995. jvirt_barray_ptr *dst_coef_arrays)
  996. /* 270 degree rotation is equivalent to
  997. * 1. Horizontal mirroring;
  998. * 2. Transposing the image.
  999. * These two steps are merged into a single processing routine.
  1000. */
  1001. {
  1002. JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
  1003. JDIMENSION x_crop_blocks, y_crop_blocks;
  1004. int ci, i, j, offset_x, offset_y;
  1005. JBLOCKARRAY src_buffer, dst_buffer;
  1006. JCOEFPTR src_ptr, dst_ptr;
  1007. jpeg_component_info *compptr;
  1008. /* Because of the horizontal mirror step, we can't process partial iMCUs
  1009. * at the (output) bottom edge properly. They just get transposed and
  1010. * not mirrored.
  1011. */
  1012. MCU_rows = srcinfo->output_width /
  1013. (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
  1014. for (ci = 0; ci < dstinfo->num_components; ci++) {
  1015. compptr = dstinfo->comp_info + ci;
  1016. comp_height = MCU_rows * compptr->v_samp_factor;
  1017. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  1018. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  1019. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  1020. dst_blk_y += compptr->v_samp_factor) {
  1021. dst_buffer = (*srcinfo->mem->access_virt_barray)
  1022. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  1023. (JDIMENSION)compptr->v_samp_factor, TRUE);
  1024. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  1025. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  1026. dst_blk_x += compptr->h_samp_factor) {
  1027. src_buffer = (*srcinfo->mem->access_virt_barray)
  1028. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  1029. dst_blk_x + x_crop_blocks,
  1030. (JDIMENSION)compptr->h_samp_factor, FALSE);
  1031. for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
  1032. dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  1033. if (y_crop_blocks + dst_blk_y < comp_height) {
  1034. /* Block is within the mirrorable area. */
  1035. src_ptr = src_buffer[offset_x]
  1036. [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
  1037. for (i = 0; i < DCTSIZE; i++) {
  1038. for (j = 0; j < DCTSIZE; j++) {
  1039. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  1040. j++;
  1041. dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
  1042. }
  1043. }
  1044. } else {
  1045. /* Edge blocks are transposed but not mirrored. */
  1046. src_ptr = src_buffer[offset_x]
  1047. [dst_blk_y + offset_y + y_crop_blocks];
  1048. for (i = 0; i < DCTSIZE; i++)
  1049. for (j = 0; j < DCTSIZE; j++)
  1050. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  1051. }
  1052. }
  1053. }
  1054. }
  1055. }
  1056. }
  1057. }
  1058. LOCAL(void)
  1059. do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  1060. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  1061. jvirt_barray_ptr *src_coef_arrays,
  1062. jvirt_barray_ptr *dst_coef_arrays)
  1063. /* 180 degree rotation is equivalent to
  1064. * 1. Vertical mirroring;
  1065. * 2. Horizontal mirroring.
  1066. * These two steps are merged into a single processing routine.
  1067. */
  1068. {
  1069. JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
  1070. JDIMENSION x_crop_blocks, y_crop_blocks;
  1071. int ci, i, j, offset_y;
  1072. JBLOCKARRAY src_buffer, dst_buffer;
  1073. JBLOCKROW src_row_ptr, dst_row_ptr;
  1074. JCOEFPTR src_ptr, dst_ptr;
  1075. jpeg_component_info *compptr;
  1076. MCU_cols = srcinfo->output_width /
  1077. (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
  1078. MCU_rows = srcinfo->output_height /
  1079. (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
  1080. for (ci = 0; ci < dstinfo->num_components; ci++) {
  1081. compptr = dstinfo->comp_info + ci;
  1082. comp_width = MCU_cols * compptr->h_samp_factor;
  1083. comp_height = MCU_rows * compptr->v_samp_factor;
  1084. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  1085. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  1086. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  1087. dst_blk_y += compptr->v_samp_factor) {
  1088. dst_buffer = (*srcinfo->mem->access_virt_barray)
  1089. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  1090. (JDIMENSION)compptr->v_samp_factor, TRUE);
  1091. if (y_crop_blocks + dst_blk_y < comp_height) {
  1092. /* Row is within the vertically mirrorable area. */
  1093. src_buffer = (*srcinfo->mem->access_virt_barray)
  1094. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  1095. comp_height - y_crop_blocks - dst_blk_y -
  1096. (JDIMENSION)compptr->v_samp_factor,
  1097. (JDIMENSION)compptr->v_samp_factor, FALSE);
  1098. } else {
  1099. /* Bottom-edge rows are only mirrored horizontally. */
  1100. src_buffer = (*srcinfo->mem->access_virt_barray)
  1101. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  1102. dst_blk_y + y_crop_blocks,
  1103. (JDIMENSION)compptr->v_samp_factor, FALSE);
  1104. }
  1105. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  1106. dst_row_ptr = dst_buffer[offset_y];
  1107. if (y_crop_blocks + dst_blk_y < comp_height) {
  1108. /* Row is within the mirrorable area. */
  1109. src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
  1110. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  1111. dst_blk_x++) {
  1112. dst_ptr = dst_row_ptr[dst_blk_x];
  1113. if (x_crop_blocks + dst_blk_x < comp_width) {
  1114. /* Process the blocks that can be mirrored both ways. */
  1115. src_ptr =
  1116. src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
  1117. for (i = 0; i < DCTSIZE; i += 2) {
  1118. /* For even row, negate every odd column. */
  1119. for (j = 0; j < DCTSIZE; j += 2) {
  1120. *dst_ptr++ = *src_ptr++;
  1121. *dst_ptr++ = -(*src_ptr++);
  1122. }
  1123. /* For odd row, negate every even column. */
  1124. for (j = 0; j < DCTSIZE; j += 2) {
  1125. *dst_ptr++ = -(*src_ptr++);
  1126. *dst_ptr++ = *src_ptr++;
  1127. }
  1128. }
  1129. } else {
  1130. /* Any remaining right-edge blocks are only mirrored vertically. */
  1131. src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
  1132. for (i = 0; i < DCTSIZE; i += 2) {
  1133. for (j = 0; j < DCTSIZE; j++)
  1134. *dst_ptr++ = *src_ptr++;
  1135. for (j = 0; j < DCTSIZE; j++)
  1136. *dst_ptr++ = -(*src_ptr++);
  1137. }
  1138. }
  1139. }
  1140. } else {
  1141. /* Remaining rows are just mirrored horizontally. */
  1142. src_row_ptr = src_buffer[offset_y];
  1143. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  1144. dst_blk_x++) {
  1145. if (x_crop_blocks + dst_blk_x < comp_width) {
  1146. /* Process the blocks that can be mirrored. */
  1147. dst_ptr = dst_row_ptr[dst_blk_x];
  1148. src_ptr =
  1149. src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
  1150. for (i = 0; i < DCTSIZE2; i += 2) {
  1151. *dst_ptr++ = *src_ptr++;
  1152. *dst_ptr++ = -(*src_ptr++);
  1153. }
  1154. } else {
  1155. /* Any remaining right-edge blocks are only copied. */
  1156. jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
  1157. dst_row_ptr + dst_blk_x, (JDIMENSION)1);
  1158. }
  1159. }
  1160. }
  1161. }
  1162. }
  1163. }
  1164. }
  1165. LOCAL(void)
  1166. do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  1167. JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  1168. jvirt_barray_ptr *src_coef_arrays,
  1169. jvirt_barray_ptr *dst_coef_arrays)
  1170. /* Transverse transpose is equivalent to
  1171. * 1. 180 degree rotation;
  1172. * 2. Transposition;
  1173. * or
  1174. * 1. Horizontal mirroring;
  1175. * 2. Transposition;
  1176. * 3. Horizontal mirroring.
  1177. * These steps are merged into a single processing routine.
  1178. */
  1179. {
  1180. JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
  1181. JDIMENSION x_crop_blocks, y_crop_blocks;
  1182. int ci, i, j, offset_x, offset_y;
  1183. JBLOCKARRAY src_buffer, dst_buffer;
  1184. JCOEFPTR src_ptr, dst_ptr;
  1185. jpeg_component_info *compptr;
  1186. MCU_cols = srcinfo->output_height /
  1187. (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
  1188. MCU_rows = srcinfo->output_width /
  1189. (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
  1190. for (ci = 0; ci < dstinfo->num_components; ci++) {
  1191. compptr = dstinfo->comp_info + ci;
  1192. comp_width = MCU_cols * compptr->h_samp_factor;
  1193. comp_height = MCU_rows * compptr->v_samp_factor;
  1194. x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  1195. y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  1196. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  1197. dst_blk_y += compptr->v_samp_factor) {
  1198. dst_buffer = (*srcinfo->mem->access_virt_barray)
  1199. ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
  1200. (JDIMENSION)compptr->v_samp_factor, TRUE);
  1201. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  1202. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  1203. dst_blk_x += compptr->h_samp_factor) {
  1204. if (x_crop_blocks + dst_blk_x < comp_width) {
  1205. /* Block is within the mirrorable area. */
  1206. src_buffer = (*srcinfo->mem->access_virt_barray)
  1207. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  1208. comp_width - x_crop_blocks - dst_blk_x -
  1209. (JDIMENSION)compptr->h_samp_factor,
  1210. (JDIMENSION)compptr->h_samp_factor, FALSE);
  1211. } else {
  1212. src_buffer = (*srcinfo->mem->access_virt_barray)
  1213. ((j_common_ptr)srcinfo, src_coef_arrays[ci],
  1214. dst_blk_x + x_crop_blocks,
  1215. (JDIMENSION)compptr->h_samp_factor, FALSE);
  1216. }
  1217. for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
  1218. dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  1219. if (y_crop_blocks + dst_blk_y < comp_height) {
  1220. if (x_crop_blocks + dst_blk_x < comp_width) {
  1221. /* Block is within the mirrorable area. */
  1222. src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
  1223. [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
  1224. for (i = 0; i < DCTSIZE; i++) {
  1225. for (j = 0; j < DCTSIZE; j++) {
  1226. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  1227. j++;
  1228. dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
  1229. }
  1230. i++;
  1231. for (j = 0; j < DCTSIZE; j++) {
  1232. dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
  1233. j++;
  1234. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  1235. }
  1236. }
  1237. } else {
  1238. /* Right-edge blocks are mirrored in y only */
  1239. src_ptr = src_buffer[offset_x]
  1240. [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
  1241. for (i = 0; i < DCTSIZE; i++) {
  1242. for (j = 0; j < DCTSIZE; j++) {
  1243. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  1244. j++;
  1245. dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
  1246. }
  1247. }
  1248. }
  1249. } else {
  1250. if (x_crop_blocks + dst_blk_x < comp_width) {
  1251. /* Bottom-edge blocks are mirrored in x only */
  1252. src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
  1253. [dst_blk_y + offset_y + y_crop_blocks];
  1254. for (i = 0; i < DCTSIZE; i++) {
  1255. for (j = 0; j < DCTSIZE; j++)
  1256. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  1257. i++;
  1258. for (j = 0; j < DCTSIZE; j++)
  1259. dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
  1260. }
  1261. } else {
  1262. /* At lower right corner, just transpose, no mirroring */
  1263. src_ptr = src_buffer[offset_x]
  1264. [dst_blk_y + offset_y + y_crop_blocks];
  1265. for (i = 0; i < DCTSIZE; i++)
  1266. for (j = 0; j < DCTSIZE; j++)
  1267. dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
  1268. }
  1269. }
  1270. }
  1271. }
  1272. }
  1273. }
  1274. }
  1275. }
  1276. /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
  1277. * Returns TRUE if valid integer found, FALSE if not.
  1278. * *strptr is advanced over the digit string, and *result is set to its value.
  1279. */
  1280. LOCAL(boolean)
  1281. jt_read_integer(const char **strptr, JDIMENSION *result)
  1282. {
  1283. const char *ptr = *strptr;
  1284. JDIMENSION val = 0;
  1285. for (; isdigit(*ptr); ptr++) {
  1286. val = val * 10 + (JDIMENSION)(*ptr - '0');
  1287. }
  1288. *result = val;
  1289. if (ptr == *strptr)
  1290. return FALSE; /* oops, no digits */
  1291. *strptr = ptr;
  1292. return TRUE;
  1293. }
  1294. /* Parse a crop specification (written in X11 geometry style).
  1295. * The routine returns TRUE if the spec string is valid, FALSE if not.
  1296. *
  1297. * The crop spec string should have the format
  1298. * <width>[{fr}]x<height>[{fr}]{+-}<xoffset>{+-}<yoffset>
  1299. * where width, height, xoffset, and yoffset are unsigned integers.
  1300. * Each of the elements can be omitted to indicate a default value.
  1301. * (A weakness of this style is that it is not possible to omit xoffset
  1302. * while specifying yoffset, since they look alike.)
  1303. *
  1304. * This code is loosely based on XParseGeometry from the X11 distribution.
  1305. */
  1306. GLOBAL(boolean)
  1307. jtransform_parse_crop_spec(jpeg_transform_info *info, const char *spec)
  1308. {
  1309. info->crop = FALSE;
  1310. info->crop_width_set = JCROP_UNSET;
  1311. info->crop_height_set = JCROP_UNSET;
  1312. info->crop_xoffset_set = JCROP_UNSET;
  1313. info->crop_yoffset_set = JCROP_UNSET;
  1314. if (isdigit(*spec)) {
  1315. /* fetch width */
  1316. if (!jt_read_integer(&spec, &info->crop_width))
  1317. return FALSE;
  1318. if (*spec == 'f' || *spec == 'F') {
  1319. spec++;
  1320. info->crop_width_set = JCROP_FORCE;
  1321. } else if (*spec == 'r' || *spec == 'R') {
  1322. spec++;
  1323. info->crop_width_set = JCROP_REFLECT;
  1324. } else
  1325. info->crop_width_set = JCROP_POS;
  1326. }
  1327. if (*spec == 'x' || *spec == 'X') {
  1328. /* fetch height */
  1329. spec++;
  1330. if (!jt_read_integer(&spec, &info->crop_height))
  1331. return FALSE;
  1332. if (*spec == 'f' || *spec == 'F') {
  1333. spec++;
  1334. info->crop_height_set = JCROP_FORCE;
  1335. } else if (*spec == 'r' || *spec == 'R') {
  1336. spec++;
  1337. info->crop_height_set = JCROP_REFLECT;
  1338. } else
  1339. info->crop_height_set = JCROP_POS;
  1340. }
  1341. if (*spec == '+' || *spec == '-') {
  1342. /* fetch xoffset */
  1343. info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
  1344. spec++;
  1345. if (!jt_read_integer(&spec, &info->crop_xoffset))
  1346. return FALSE;
  1347. }
  1348. if (*spec == '+' || *spec == '-') {
  1349. /* fetch yoffset */
  1350. info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
  1351. spec++;
  1352. if (!jt_read_integer(&spec, &info->crop_yoffset))
  1353. return FALSE;
  1354. }
  1355. /* We had better have gotten to the end of the string. */
  1356. if (*spec != '\0')
  1357. return FALSE;
  1358. info->crop = TRUE;
  1359. return TRUE;
  1360. }
  1361. /* Trim off any partial iMCUs on the indicated destination edge */
  1362. LOCAL(void)
  1363. trim_right_edge(jpeg_transform_info *info, JDIMENSION full_width)
  1364. {
  1365. JDIMENSION MCU_cols;
  1366. MCU_cols = info->output_width / info->iMCU_sample_width;
  1367. if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
  1368. full_width / info->iMCU_sample_width)
  1369. info->output_width = MCU_cols * info->iMCU_sample_width;
  1370. }
  1371. LOCAL(void)
  1372. trim_bottom_edge(jpeg_transform_info *info, JDIMENSION full_height)
  1373. {
  1374. JDIMENSION MCU_rows;
  1375. MCU_rows = info->output_height / info->iMCU_sample_height;
  1376. if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
  1377. full_height / info->iMCU_sample_height)
  1378. info->output_height = MCU_rows * info->iMCU_sample_height;
  1379. }
  1380. /* Request any required workspace.
  1381. *
  1382. * This routine figures out the size that the output image will be
  1383. * (which implies that all the transform parameters must be set before
  1384. * it is called).
  1385. *
  1386. * We allocate the workspace virtual arrays from the source decompression
  1387. * object, so that all the arrays (both the original data and the workspace)
  1388. * will be taken into account while making memory management decisions.
  1389. * Hence, this routine must be called after jpeg_read_header (which reads
  1390. * the image dimensions) and before jpeg_read_coefficients (which realizes
  1391. * the source's virtual arrays).
  1392. *
  1393. * This function returns FALSE right away if -perfect is given
  1394. * and transformation is not perfect. Otherwise returns TRUE.
  1395. */
  1396. GLOBAL(boolean)
  1397. jtransform_request_workspace(j_decompress_ptr srcinfo,
  1398. jpeg_transform_info *info)
  1399. {
  1400. jvirt_barray_ptr *coef_arrays;
  1401. boolean need_workspace, transpose_it;
  1402. jpeg_component_info *compptr;
  1403. JDIMENSION xoffset, yoffset, dtemp;
  1404. JDIMENSION width_in_iMCUs, height_in_iMCUs;
  1405. JDIMENSION width_in_blocks, height_in_blocks;
  1406. int itemp, ci, h_samp_factor, v_samp_factor;
  1407. /* Determine number of components in output image */
  1408. if (info->force_grayscale &&
  1409. srcinfo->jpeg_color_space == JCS_YCbCr &&
  1410. srcinfo->num_components == 3)
  1411. /* We'll only process the first component */
  1412. info->num_components = 1;
  1413. else
  1414. /* Process all the components */
  1415. info->num_components = srcinfo->num_components;
  1416. /* Compute output image dimensions and related values. */
  1417. #if JPEG_LIB_VERSION >= 80
  1418. jpeg_core_output_dimensions(srcinfo);
  1419. #else
  1420. srcinfo->output_width = srcinfo->image_width;
  1421. srcinfo->output_height = srcinfo->image_height;
  1422. #endif
  1423. /* Return right away if -perfect is given and transformation is not perfect.
  1424. */
  1425. if (info->perfect) {
  1426. if (info->num_components == 1) {
  1427. if (!jtransform_perfect_transform(srcinfo->output_width,
  1428. srcinfo->output_height,
  1429. srcinfo->_min_DCT_h_scaled_size,
  1430. srcinfo->_min_DCT_v_scaled_size,
  1431. info->transform))
  1432. return FALSE;
  1433. } else {
  1434. if (!jtransform_perfect_transform(srcinfo->output_width,
  1435. srcinfo->output_height,
  1436. srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
  1437. srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
  1438. info->transform))
  1439. return FALSE;
  1440. }
  1441. }
  1442. /* If there is only one output component, force the iMCU size to be 1;
  1443. * else use the source iMCU size. (This allows us to do the right thing
  1444. * when reducing color to grayscale, and also provides a handy way of
  1445. * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
  1446. */
  1447. switch (info->transform) {
  1448. case JXFORM_TRANSPOSE:
  1449. case JXFORM_TRANSVERSE:
  1450. case JXFORM_ROT_90:
  1451. case JXFORM_ROT_270:
  1452. info->output_width = srcinfo->output_height;
  1453. info->output_height = srcinfo->output_width;
  1454. if (info->num_components == 1) {
  1455. info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
  1456. info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
  1457. } else {
  1458. info->iMCU_sample_width =
  1459. srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
  1460. info->iMCU_sample_height =
  1461. srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
  1462. }
  1463. break;
  1464. default:
  1465. info->output_width = srcinfo->output_width;
  1466. info->output_height = srcinfo->output_height;
  1467. if (info->num_components == 1) {
  1468. info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
  1469. info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
  1470. } else {
  1471. info->iMCU_sample_width =
  1472. srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
  1473. info->iMCU_sample_height =
  1474. srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
  1475. }
  1476. break;
  1477. }
  1478. /* If cropping has been requested, compute the crop area's position and
  1479. * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
  1480. */
  1481. if (info->crop) {
  1482. /* Insert default values for unset crop parameters */
  1483. if (info->crop_xoffset_set == JCROP_UNSET)
  1484. info->crop_xoffset = 0; /* default to +0 */
  1485. if (info->crop_yoffset_set == JCROP_UNSET)
  1486. info->crop_yoffset = 0; /* default to +0 */
  1487. if (info->crop_width_set == JCROP_UNSET) {
  1488. if (info->crop_xoffset >= info->output_width)
  1489. ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
  1490. info->crop_width = info->output_width - info->crop_xoffset;
  1491. } else {
  1492. /* Check for crop extension */
  1493. if (info->crop_width > info->output_width) {
  1494. /* Crop extension does not work when transforming! */
  1495. if (info->transform != JXFORM_NONE ||
  1496. info->crop_xoffset >= info->crop_width ||
  1497. info->crop_xoffset > info->crop_width - info->output_width)
  1498. ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
  1499. } else {
  1500. if (info->crop_xoffset >= info->output_width ||
  1501. info->crop_width <= 0 ||
  1502. info->crop_xoffset > info->output_width - info->crop_width)
  1503. ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
  1504. }
  1505. }
  1506. if (info->crop_height_set == JCROP_UNSET) {
  1507. if (info->crop_yoffset >= info->output_height)
  1508. ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
  1509. info->crop_height = info->output_height - info->crop_yoffset;
  1510. } else {
  1511. /* Check for crop extension */
  1512. if (info->crop_height > info->output_height) {
  1513. /* Crop extension does not work when transforming! */
  1514. if (info->transform != JXFORM_NONE ||
  1515. info->crop_yoffset >= info->crop_height ||
  1516. info->crop_yoffset > info->crop_height - info->output_height)
  1517. ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
  1518. } else {
  1519. if (info->crop_yoffset >= info->output_height ||
  1520. info->crop_height <= 0 ||
  1521. info->crop_yoffset > info->output_height - info->crop_height)
  1522. ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
  1523. }
  1524. }
  1525. /* Convert negative crop offsets into regular offsets */
  1526. if (info->crop_xoffset_set != JCROP_NEG)
  1527. xoffset = info->crop_xoffset;
  1528. else if (info->crop_width > info->output_width) /* crop extension */
  1529. xoffset = info->crop_width - info->output_width - info->crop_xoffset;
  1530. else
  1531. xoffset = info->output_width - info->crop_width - info->crop_xoffset;
  1532. if (info->crop_yoffset_set != JCROP_NEG)
  1533. yoffset = info->crop_yoffset;
  1534. else if (info->crop_height > info->output_height) /* crop extension */
  1535. yoffset = info->crop_height - info->output_height - info->crop_yoffset;
  1536. else
  1537. yoffset = info->output_height - info->crop_height - info->crop_yoffset;
  1538. /* Now adjust so that upper left corner falls at an iMCU boundary */
  1539. switch (info->transform) {
  1540. case JXFORM_DROP:
  1541. /* Ensure the effective drop region will not exceed the requested */
  1542. itemp = info->iMCU_sample_width;
  1543. dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp);
  1544. xoffset += dtemp;
  1545. if (info->crop_width <= dtemp)
  1546. info->drop_width = 0;
  1547. else if (xoffset + info->crop_width - dtemp == info->output_width)
  1548. /* Matching right edge: include partial iMCU */
  1549. info->drop_width = (info->crop_width - dtemp + itemp - 1) / itemp;
  1550. else
  1551. info->drop_width = (info->crop_width - dtemp) / itemp;
  1552. itemp = info->iMCU_sample_height;
  1553. dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp);
  1554. yoffset += dtemp;
  1555. if (info->crop_height <= dtemp)
  1556. info->drop_height = 0;
  1557. else if (yoffset + info->crop_height - dtemp == info->output_height)
  1558. /* Matching bottom edge: include partial iMCU */
  1559. info->drop_height = (info->crop_height - dtemp + itemp - 1) / itemp;
  1560. else
  1561. info->drop_height = (info->crop_height - dtemp) / itemp;
  1562. /* Check if sampling factors match for dropping */
  1563. if (info->drop_width != 0 && info->drop_height != 0)
  1564. for (ci = 0; ci < info->num_components &&
  1565. ci < info->drop_ptr->num_components; ci++) {
  1566. if (info->drop_ptr->comp_info[ci].h_samp_factor *
  1567. srcinfo->max_h_samp_factor !=
  1568. srcinfo->comp_info[ci].h_samp_factor *
  1569. info->drop_ptr->max_h_samp_factor)
  1570. ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
  1571. info->drop_ptr->comp_info[ci].h_samp_factor,
  1572. info->drop_ptr->max_h_samp_factor,
  1573. srcinfo->comp_info[ci].h_samp_factor,
  1574. srcinfo->max_h_samp_factor, 'h');
  1575. if (info->drop_ptr->comp_info[ci].v_samp_factor *
  1576. srcinfo->max_v_samp_factor !=
  1577. srcinfo->comp_info[ci].v_samp_factor *
  1578. info->drop_ptr->max_v_samp_factor)
  1579. ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
  1580. info->drop_ptr->comp_info[ci].v_samp_factor,
  1581. info->drop_ptr->max_v_samp_factor,
  1582. srcinfo->comp_info[ci].v_samp_factor,
  1583. srcinfo->max_v_samp_factor, 'v');
  1584. }
  1585. break;
  1586. case JXFORM_WIPE:
  1587. /* Ensure the effective wipe region will cover the requested */
  1588. info->drop_width = (JDIMENSION)jdiv_round_up
  1589. ((long)(info->crop_width + (xoffset % info->iMCU_sample_width)),
  1590. (long)info->iMCU_sample_width);
  1591. info->drop_height = (JDIMENSION)jdiv_round_up
  1592. ((long)(info->crop_height + (yoffset % info->iMCU_sample_height)),
  1593. (long)info->iMCU_sample_height);
  1594. break;
  1595. default:
  1596. /* Ensure the effective crop region will cover the requested */
  1597. if (info->crop_width_set == JCROP_FORCE ||
  1598. info->crop_width > info->output_width)
  1599. info->output_width = info->crop_width;
  1600. else
  1601. info->output_width =
  1602. info->crop_width + (xoffset % info->iMCU_sample_width);
  1603. if (info->crop_height_set == JCROP_FORCE ||
  1604. info->crop_height > info->output_height)
  1605. info->output_height = info->crop_height;
  1606. else
  1607. info->output_height =
  1608. info->crop_height + (yoffset % info->iMCU_sample_height);
  1609. }
  1610. /* Save x/y offsets measured in iMCUs */
  1611. info->x_crop_offset = xoffset / info->iMCU_sample_width;
  1612. info->y_crop_offset = yoffset / info->iMCU_sample_height;
  1613. } else {
  1614. info->x_crop_offset = 0;
  1615. info->y_crop_offset = 0;
  1616. }
  1617. /* Figure out whether we need workspace arrays,
  1618. * and if so whether they are transposed relative to the source.
  1619. */
  1620. need_workspace = FALSE;
  1621. transpose_it = FALSE;
  1622. switch (info->transform) {
  1623. case JXFORM_NONE:
  1624. if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
  1625. info->output_width > srcinfo->output_width ||
  1626. info->output_height > srcinfo->output_height)
  1627. need_workspace = TRUE;
  1628. /* No workspace needed if neither cropping nor transforming */
  1629. break;
  1630. case JXFORM_FLIP_H:
  1631. if (info->trim)
  1632. trim_right_edge(info, srcinfo->output_width);
  1633. if (info->y_crop_offset != 0 || info->slow_hflip)
  1634. need_workspace = TRUE;
  1635. /* do_flip_h_no_crop doesn't need a workspace array */
  1636. break;
  1637. case JXFORM_FLIP_V:
  1638. if (info->trim)
  1639. trim_bottom_edge(info, srcinfo->output_height);
  1640. /* Need workspace arrays having same dimensions as source image. */
  1641. need_workspace = TRUE;
  1642. break;
  1643. case JXFORM_TRANSPOSE:
  1644. /* transpose does NOT have to trim anything */
  1645. /* Need workspace arrays having transposed dimensions. */
  1646. need_workspace = TRUE;
  1647. transpose_it = TRUE;
  1648. break;
  1649. case JXFORM_TRANSVERSE:
  1650. if (info->trim) {
  1651. trim_right_edge(info, srcinfo->output_height);
  1652. trim_bottom_edge(info, srcinfo->output_width);
  1653. }
  1654. /* Need workspace arrays having transposed dimensions. */
  1655. need_workspace = TRUE;
  1656. transpose_it = TRUE;
  1657. break;
  1658. case JXFORM_ROT_90:
  1659. if (info->trim)
  1660. trim_right_edge(info, srcinfo->output_height);
  1661. /* Need workspace arrays having transposed dimensions. */
  1662. need_workspace = TRUE;
  1663. transpose_it = TRUE;
  1664. break;
  1665. case JXFORM_ROT_180:
  1666. if (info->trim) {
  1667. trim_right_edge(info, srcinfo->output_width);
  1668. trim_bottom_edge(info, srcinfo->output_height);
  1669. }
  1670. /* Need workspace arrays having same dimensions as source image. */
  1671. need_workspace = TRUE;
  1672. break;
  1673. case JXFORM_ROT_270:
  1674. if (info->trim)
  1675. trim_bottom_edge(info, srcinfo->output_width);
  1676. /* Need workspace arrays having transposed dimensions. */
  1677. need_workspace = TRUE;
  1678. transpose_it = TRUE;
  1679. break;
  1680. case JXFORM_WIPE:
  1681. break;
  1682. case JXFORM_DROP:
  1683. break;
  1684. }
  1685. /* Allocate workspace if needed.
  1686. * Note that we allocate arrays padded out to the next iMCU boundary,
  1687. * so that transform routines need not worry about missing edge blocks.
  1688. */
  1689. if (need_workspace) {
  1690. coef_arrays = (jvirt_barray_ptr *)
  1691. (*srcinfo->mem->alloc_small) ((j_common_ptr)srcinfo, JPOOL_IMAGE,
  1692. sizeof(jvirt_barray_ptr) * info->num_components);
  1693. width_in_iMCUs = (JDIMENSION)
  1694. jdiv_round_up((long)info->output_width, (long)info->iMCU_sample_width);
  1695. height_in_iMCUs = (JDIMENSION)
  1696. jdiv_round_up((long)info->output_height, (long)info->iMCU_sample_height);
  1697. for (ci = 0; ci < info->num_components; ci++) {
  1698. compptr = srcinfo->comp_info + ci;
  1699. if (info->num_components == 1) {
  1700. /* we're going to force samp factors to 1x1 in this case */
  1701. h_samp_factor = v_samp_factor = 1;
  1702. } else if (transpose_it) {
  1703. h_samp_factor = compptr->v_samp_factor;
  1704. v_samp_factor = compptr->h_samp_factor;
  1705. } else {
  1706. h_samp_factor = compptr->h_samp_factor;
  1707. v_samp_factor = compptr->v_samp_factor;
  1708. }
  1709. width_in_blocks = width_in_iMCUs * h_samp_factor;
  1710. height_in_blocks = height_in_iMCUs * v_samp_factor;
  1711. coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
  1712. ((j_common_ptr)srcinfo, JPOOL_IMAGE, FALSE,
  1713. width_in_blocks, height_in_blocks, (JDIMENSION)v_samp_factor);
  1714. }
  1715. info->workspace_coef_arrays = coef_arrays;
  1716. } else
  1717. info->workspace_coef_arrays = NULL;
  1718. return TRUE;
  1719. }
  1720. /* Transpose destination image parameters */
  1721. LOCAL(void)
  1722. transpose_critical_parameters(j_compress_ptr dstinfo)
  1723. {
  1724. int tblno, i, j, ci, itemp;
  1725. jpeg_component_info *compptr;
  1726. JQUANT_TBL *qtblptr;
  1727. JDIMENSION jtemp;
  1728. UINT16 qtemp;
  1729. /* Transpose image dimensions */
  1730. jtemp = dstinfo->image_width;
  1731. dstinfo->image_width = dstinfo->image_height;
  1732. dstinfo->image_height = jtemp;
  1733. #if JPEG_LIB_VERSION >= 70
  1734. itemp = dstinfo->min_DCT_h_scaled_size;
  1735. dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
  1736. dstinfo->min_DCT_v_scaled_size = itemp;
  1737. #endif
  1738. /* Transpose sampling factors */
  1739. for (ci = 0; ci < dstinfo->num_components; ci++) {
  1740. compptr = dstinfo->comp_info + ci;
  1741. itemp = compptr->h_samp_factor;
  1742. compptr->h_samp_factor = compptr->v_samp_factor;
  1743. compptr->v_samp_factor = itemp;
  1744. }
  1745. /* Transpose quantization tables */
  1746. for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
  1747. qtblptr = dstinfo->quant_tbl_ptrs[tblno];
  1748. if (qtblptr != NULL) {
  1749. for (i = 0; i < DCTSIZE; i++) {
  1750. for (j = 0; j < i; j++) {
  1751. qtemp = qtblptr->quantval[i * DCTSIZE + j];
  1752. qtblptr->quantval[i * DCTSIZE + j] =
  1753. qtblptr->quantval[j * DCTSIZE + i];
  1754. qtblptr->quantval[j * DCTSIZE + i] = qtemp;
  1755. }
  1756. }
  1757. }
  1758. }
  1759. }
  1760. /* Adjust Exif image parameters.
  1761. *
  1762. * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
  1763. */
  1764. LOCAL(void)
  1765. adjust_exif_parameters(JOCTET *data, unsigned int length, JDIMENSION new_width,
  1766. JDIMENSION new_height)
  1767. {
  1768. boolean is_motorola; /* Flag for byte order */
  1769. unsigned int number_of_tags, tagnum;
  1770. unsigned int firstoffset, offset;
  1771. JDIMENSION new_value;
  1772. if (length < 12) return; /* Length of an IFD entry */
  1773. /* Discover byte order */
  1774. if (data[0] == 0x49 && data[1] == 0x49)
  1775. is_motorola = FALSE;
  1776. else if (data[0] == 0x4D && data[1] == 0x4D)
  1777. is_motorola = TRUE;
  1778. else
  1779. return;
  1780. /* Check Tag Mark */
  1781. if (is_motorola) {
  1782. if (data[2] != 0) return;
  1783. if (data[3] != 0x2A) return;
  1784. } else {
  1785. if (data[3] != 0) return;
  1786. if (data[2] != 0x2A) return;
  1787. }
  1788. /* Get first IFD offset (offset to IFD0) */
  1789. if (is_motorola) {
  1790. if (data[4] != 0) return;
  1791. if (data[5] != 0) return;
  1792. firstoffset = data[6];
  1793. firstoffset <<= 8;
  1794. firstoffset += data[7];
  1795. } else {
  1796. if (data[7] != 0) return;
  1797. if (data[6] != 0) return;
  1798. firstoffset = data[5];
  1799. firstoffset <<= 8;
  1800. firstoffset += data[4];
  1801. }
  1802. if (firstoffset > length - 2) return; /* check end of data segment */
  1803. /* Get the number of directory entries contained in this IFD */
  1804. if (is_motorola) {
  1805. number_of_tags = data[firstoffset];
  1806. number_of_tags <<= 8;
  1807. number_of_tags += data[firstoffset + 1];
  1808. } else {
  1809. number_of_tags = data[firstoffset + 1];
  1810. number_of_tags <<= 8;
  1811. number_of_tags += data[firstoffset];
  1812. }
  1813. if (number_of_tags == 0) return;
  1814. firstoffset += 2;
  1815. /* Search for ExifSubIFD offset Tag in IFD0 */
  1816. for (;;) {
  1817. if (firstoffset > length - 12) return; /* check end of data segment */
  1818. /* Get Tag number */
  1819. if (is_motorola) {
  1820. tagnum = data[firstoffset];
  1821. tagnum <<= 8;
  1822. tagnum += data[firstoffset + 1];
  1823. } else {
  1824. tagnum = data[firstoffset + 1];
  1825. tagnum <<= 8;
  1826. tagnum += data[firstoffset];
  1827. }
  1828. if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
  1829. if (--number_of_tags == 0) return;
  1830. firstoffset += 12;
  1831. }
  1832. /* Get the ExifSubIFD offset */
  1833. if (is_motorola) {
  1834. if (data[firstoffset + 8] != 0) return;
  1835. if (data[firstoffset + 9] != 0) return;
  1836. offset = data[firstoffset + 10];
  1837. offset <<= 8;
  1838. offset += data[firstoffset + 11];
  1839. } else {
  1840. if (data[firstoffset + 11] != 0) return;
  1841. if (data[firstoffset + 10] != 0) return;
  1842. offset = data[firstoffset + 9];
  1843. offset <<= 8;
  1844. offset += data[firstoffset + 8];
  1845. }
  1846. if (offset > length - 2) return; /* check end of data segment */
  1847. /* Get the number of directory entries contained in this SubIFD */
  1848. if (is_motorola) {
  1849. number_of_tags = data[offset];
  1850. number_of_tags <<= 8;
  1851. number_of_tags += data[offset + 1];
  1852. } else {
  1853. number_of_tags = data[offset + 1];
  1854. number_of_tags <<= 8;
  1855. number_of_tags += data[offset];
  1856. }
  1857. if (number_of_tags < 2) return;
  1858. offset += 2;
  1859. /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
  1860. do {
  1861. if (offset > length - 12) return; /* check end of data segment */
  1862. /* Get Tag number */
  1863. if (is_motorola) {
  1864. tagnum = data[offset];
  1865. tagnum <<= 8;
  1866. tagnum += data[offset + 1];
  1867. } else {
  1868. tagnum = data[offset + 1];
  1869. tagnum <<= 8;
  1870. tagnum += data[offset];
  1871. }
  1872. if (tagnum == 0xA002 || tagnum == 0xA003) {
  1873. if (tagnum == 0xA002)
  1874. new_value = new_width; /* ExifImageWidth Tag */
  1875. else
  1876. new_value = new_height; /* ExifImageHeight Tag */
  1877. if (is_motorola) {
  1878. data[offset + 2] = 0; /* Format = unsigned long (4 octets) */
  1879. data[offset + 3] = 4;
  1880. data[offset + 4] = 0; /* Number Of Components = 1 */
  1881. data[offset + 5] = 0;
  1882. data[offset + 6] = 0;
  1883. data[offset + 7] = 1;
  1884. data[offset + 8] = 0;
  1885. data[offset + 9] = 0;
  1886. data[offset + 10] = (JOCTET)((new_value >> 8) & 0xFF);
  1887. data[offset + 11] = (JOCTET)(new_value & 0xFF);
  1888. } else {
  1889. data[offset + 2] = 4; /* Format = unsigned long (4 octets) */
  1890. data[offset + 3] = 0;
  1891. data[offset + 4] = 1; /* Number Of Components = 1 */
  1892. data[offset + 5] = 0;
  1893. data[offset + 6] = 0;
  1894. data[offset + 7] = 0;
  1895. data[offset + 8] = (JOCTET)(new_value & 0xFF);
  1896. data[offset + 9] = (JOCTET)((new_value >> 8) & 0xFF);
  1897. data[offset + 10] = 0;
  1898. data[offset + 11] = 0;
  1899. }
  1900. }
  1901. offset += 12;
  1902. } while (--number_of_tags);
  1903. }
  1904. /* Adjust output image parameters as needed.
  1905. *
  1906. * This must be called after jpeg_copy_critical_parameters()
  1907. * and before jpeg_write_coefficients().
  1908. *
  1909. * The return value is the set of virtual coefficient arrays to be written
  1910. * (either the ones allocated by jtransform_request_workspace, or the
  1911. * original source data arrays). The caller will need to pass this value
  1912. * to jpeg_write_coefficients().
  1913. */
  1914. GLOBAL(jvirt_barray_ptr *)
  1915. jtransform_adjust_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  1916. jvirt_barray_ptr *src_coef_arrays,
  1917. jpeg_transform_info *info)
  1918. {
  1919. /* If force-to-grayscale is requested, adjust destination parameters */
  1920. if (info->force_grayscale) {
  1921. /* First, ensure we have YCbCr or grayscale data, and that the source's
  1922. * Y channel is full resolution. (No reasonable person would make Y
  1923. * be less than full resolution, so actually coping with that case
  1924. * isn't worth extra code space. But we check it to avoid crashing.)
  1925. */
  1926. if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
  1927. dstinfo->num_components == 3) ||
  1928. (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
  1929. dstinfo->num_components == 1)) &&
  1930. srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
  1931. srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
  1932. /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
  1933. * properly. Among other things, it sets the target h_samp_factor &
  1934. * v_samp_factor to 1, which typically won't match the source.
  1935. * We have to preserve the source's quantization table number, however.
  1936. */
  1937. int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
  1938. jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
  1939. dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
  1940. } else {
  1941. /* Sorry, can't do it */
  1942. ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
  1943. }
  1944. } else if (info->num_components == 1) {
  1945. /* For a single-component source, we force the destination sampling factors
  1946. * to 1x1, with or without force_grayscale. This is useful because some
  1947. * decoders choke on grayscale images with other sampling factors.
  1948. */
  1949. dstinfo->comp_info[0].h_samp_factor = 1;
  1950. dstinfo->comp_info[0].v_samp_factor = 1;
  1951. }
  1952. /* Correct the destination's image dimensions as necessary
  1953. * for rotate/flip, resize, and crop operations.
  1954. */
  1955. #if JPEG_LIB_VERSION >= 80
  1956. dstinfo->jpeg_width = info->output_width;
  1957. dstinfo->jpeg_height = info->output_height;
  1958. #endif
  1959. /* Transpose destination image parameters, adjust quantization */
  1960. switch (info->transform) {
  1961. case JXFORM_TRANSPOSE:
  1962. case JXFORM_TRANSVERSE:
  1963. case JXFORM_ROT_90:
  1964. case JXFORM_ROT_270:
  1965. #if JPEG_LIB_VERSION < 80
  1966. dstinfo->image_width = info->output_height;
  1967. dstinfo->image_height = info->output_width;
  1968. #endif
  1969. transpose_critical_parameters(dstinfo);
  1970. break;
  1971. case JXFORM_DROP:
  1972. if (info->drop_width != 0 && info->drop_height != 0)
  1973. adjust_quant(srcinfo, src_coef_arrays,
  1974. info->drop_ptr, info->drop_coef_arrays,
  1975. info->trim, dstinfo);
  1976. break;
  1977. default:
  1978. #if JPEG_LIB_VERSION < 80
  1979. dstinfo->image_width = info->output_width;
  1980. dstinfo->image_height = info->output_height;
  1981. #endif
  1982. break;
  1983. }
  1984. /* Adjust Exif properties */
  1985. if (srcinfo->marker_list != NULL &&
  1986. srcinfo->marker_list->marker == JPEG_APP0 + 1 &&
  1987. srcinfo->marker_list->data_length >= 6 &&
  1988. srcinfo->marker_list->data[0] == 0x45 &&
  1989. srcinfo->marker_list->data[1] == 0x78 &&
  1990. srcinfo->marker_list->data[2] == 0x69 &&
  1991. srcinfo->marker_list->data[3] == 0x66 &&
  1992. srcinfo->marker_list->data[4] == 0 &&
  1993. srcinfo->marker_list->data[5] == 0) {
  1994. /* Suppress output of JFIF marker */
  1995. dstinfo->write_JFIF_header = FALSE;
  1996. /* Adjust Exif image parameters */
  1997. #if JPEG_LIB_VERSION >= 80
  1998. if (dstinfo->jpeg_width != srcinfo->image_width ||
  1999. dstinfo->jpeg_height != srcinfo->image_height)
  2000. /* Align data segment to start of TIFF structure for parsing */
  2001. adjust_exif_parameters(srcinfo->marker_list->data + 6,
  2002. srcinfo->marker_list->data_length - 6,
  2003. dstinfo->jpeg_width, dstinfo->jpeg_height);
  2004. #else
  2005. if (dstinfo->image_width != srcinfo->image_width ||
  2006. dstinfo->image_height != srcinfo->image_height)
  2007. /* Align data segment to start of TIFF structure for parsing */
  2008. adjust_exif_parameters(srcinfo->marker_list->data + 6,
  2009. srcinfo->marker_list->data_length - 6,
  2010. dstinfo->image_width, dstinfo->image_height);
  2011. #endif
  2012. }
  2013. /* Return the appropriate output data set */
  2014. if (info->workspace_coef_arrays != NULL)
  2015. return info->workspace_coef_arrays;
  2016. return src_coef_arrays;
  2017. }
  2018. /* Execute the actual transformation, if any.
  2019. *
  2020. * This must be called *after* jpeg_write_coefficients, because it depends
  2021. * on jpeg_write_coefficients to have computed subsidiary values such as
  2022. * the per-component width and height fields in the destination object.
  2023. *
  2024. * Note that some transformations will modify the source data arrays!
  2025. */
  2026. GLOBAL(void)
  2027. jtransform_execute_transform(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  2028. jvirt_barray_ptr *src_coef_arrays,
  2029. jpeg_transform_info *info)
  2030. {
  2031. jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
  2032. /* Note: conditions tested here should match those in switch statement
  2033. * in jtransform_request_workspace()
  2034. */
  2035. switch (info->transform) {
  2036. case JXFORM_NONE:
  2037. if (info->output_width > srcinfo->output_width ||
  2038. info->output_height > srcinfo->output_height) {
  2039. if (info->output_width > srcinfo->output_width &&
  2040. info->crop_width_set == JCROP_REFLECT)
  2041. do_crop_ext_reflect(srcinfo, dstinfo,
  2042. info->x_crop_offset, info->y_crop_offset,
  2043. src_coef_arrays, dst_coef_arrays);
  2044. else if (info->output_width > srcinfo->output_width &&
  2045. info->crop_width_set == JCROP_FORCE)
  2046. do_crop_ext_flat(srcinfo, dstinfo,
  2047. info->x_crop_offset, info->y_crop_offset,
  2048. src_coef_arrays, dst_coef_arrays);
  2049. else
  2050. do_crop_ext_zero(srcinfo, dstinfo,
  2051. info->x_crop_offset, info->y_crop_offset,
  2052. src_coef_arrays, dst_coef_arrays);
  2053. } else if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
  2054. do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2055. src_coef_arrays, dst_coef_arrays);
  2056. break;
  2057. case JXFORM_FLIP_H:
  2058. if (info->y_crop_offset != 0 || info->slow_hflip)
  2059. do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2060. src_coef_arrays, dst_coef_arrays);
  2061. else
  2062. do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
  2063. src_coef_arrays);
  2064. break;
  2065. case JXFORM_FLIP_V:
  2066. do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2067. src_coef_arrays, dst_coef_arrays);
  2068. break;
  2069. case JXFORM_TRANSPOSE:
  2070. do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2071. src_coef_arrays, dst_coef_arrays);
  2072. break;
  2073. case JXFORM_TRANSVERSE:
  2074. do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2075. src_coef_arrays, dst_coef_arrays);
  2076. break;
  2077. case JXFORM_ROT_90:
  2078. do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2079. src_coef_arrays, dst_coef_arrays);
  2080. break;
  2081. case JXFORM_ROT_180:
  2082. do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2083. src_coef_arrays, dst_coef_arrays);
  2084. break;
  2085. case JXFORM_ROT_270:
  2086. do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2087. src_coef_arrays, dst_coef_arrays);
  2088. break;
  2089. case JXFORM_WIPE:
  2090. if (info->crop_width_set == JCROP_REFLECT &&
  2091. info->y_crop_offset == 0 && info->drop_height ==
  2092. (JDIMENSION)jdiv_round_up
  2093. ((long)info->output_height, (long)info->iMCU_sample_height) &&
  2094. (info->x_crop_offset == 0 ||
  2095. info->x_crop_offset + info->drop_width ==
  2096. (JDIMENSION)jdiv_round_up
  2097. ((long)info->output_width, (long)info->iMCU_sample_width)))
  2098. do_reflect(srcinfo, dstinfo, info->x_crop_offset,
  2099. src_coef_arrays, info->drop_width, info->drop_height);
  2100. else if (info->crop_width_set == JCROP_FORCE)
  2101. do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2102. src_coef_arrays, info->drop_width, info->drop_height);
  2103. else
  2104. do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2105. src_coef_arrays, info->drop_width, info->drop_height);
  2106. break;
  2107. case JXFORM_DROP:
  2108. if (info->drop_width != 0 && info->drop_height != 0)
  2109. do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  2110. src_coef_arrays, info->drop_ptr, info->drop_coef_arrays,
  2111. info->drop_width, info->drop_height);
  2112. break;
  2113. }
  2114. }
  2115. /* jtransform_perfect_transform
  2116. *
  2117. * Determine whether lossless transformation is perfectly
  2118. * possible for a specified image and transformation.
  2119. *
  2120. * Inputs:
  2121. * image_width, image_height: source image dimensions.
  2122. * MCU_width, MCU_height: pixel dimensions of MCU.
  2123. * transform: transformation identifier.
  2124. * Parameter sources from initialized jpeg_struct
  2125. * (after reading source header):
  2126. * image_width = cinfo.image_width
  2127. * image_height = cinfo.image_height
  2128. * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
  2129. * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
  2130. * Result:
  2131. * TRUE = perfect transformation possible
  2132. * FALSE = perfect transformation not possible
  2133. * (may use custom action then)
  2134. */
  2135. GLOBAL(boolean)
  2136. jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
  2137. int MCU_width, int MCU_height,
  2138. JXFORM_CODE transform)
  2139. {
  2140. boolean result = TRUE; /* initialize TRUE */
  2141. switch (transform) {
  2142. case JXFORM_FLIP_H:
  2143. case JXFORM_ROT_270:
  2144. if (image_width % (JDIMENSION)MCU_width)
  2145. result = FALSE;
  2146. break;
  2147. case JXFORM_FLIP_V:
  2148. case JXFORM_ROT_90:
  2149. if (image_height % (JDIMENSION)MCU_height)
  2150. result = FALSE;
  2151. break;
  2152. case JXFORM_TRANSVERSE:
  2153. case JXFORM_ROT_180:
  2154. if (image_width % (JDIMENSION)MCU_width)
  2155. result = FALSE;
  2156. if (image_height % (JDIMENSION)MCU_height)
  2157. result = FALSE;
  2158. break;
  2159. default:
  2160. break;
  2161. }
  2162. return result;
  2163. }
  2164. #endif /* TRANSFORMS_SUPPORTED */
  2165. /* Setup decompression object to save desired markers in memory.
  2166. * This must be called before jpeg_read_header() to have the desired effect.
  2167. */
  2168. GLOBAL(void)
  2169. jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
  2170. {
  2171. #ifdef SAVE_MARKERS_SUPPORTED
  2172. int m;
  2173. /* Save comments except under NONE option */
  2174. if (option != JCOPYOPT_NONE && option != JCOPYOPT_ICC) {
  2175. jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
  2176. }
  2177. /* Save all types of APPn markers iff ALL option */
  2178. if (option == JCOPYOPT_ALL || option == JCOPYOPT_ALL_EXCEPT_ICC) {
  2179. for (m = 0; m < 16; m++) {
  2180. if (option == JCOPYOPT_ALL_EXCEPT_ICC && m == 2)
  2181. continue;
  2182. jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
  2183. }
  2184. }
  2185. /* Save only APP2 markers if ICC option selected */
  2186. if (option == JCOPYOPT_ICC) {
  2187. jpeg_save_markers(srcinfo, JPEG_APP0 + 2, 0xFFFF);
  2188. }
  2189. #endif /* SAVE_MARKERS_SUPPORTED */
  2190. }
  2191. /* Copy markers saved in the given source object to the destination object.
  2192. * This should be called just after jpeg_start_compress() or
  2193. * jpeg_write_coefficients().
  2194. * Note that those routines will have written the SOI, and also the
  2195. * JFIF APP0 or Adobe APP14 markers if selected.
  2196. */
  2197. GLOBAL(void)
  2198. jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  2199. JCOPY_OPTION option)
  2200. {
  2201. jpeg_saved_marker_ptr marker;
  2202. /* In the current implementation, we don't actually need to examine the
  2203. * option flag here; we just copy everything that got saved.
  2204. * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
  2205. * if the encoder library already wrote one.
  2206. */
  2207. for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
  2208. if (dstinfo->write_JFIF_header &&
  2209. marker->marker == JPEG_APP0 &&
  2210. marker->data_length >= 5 &&
  2211. marker->data[0] == 0x4A &&
  2212. marker->data[1] == 0x46 &&
  2213. marker->data[2] == 0x49 &&
  2214. marker->data[3] == 0x46 &&
  2215. marker->data[4] == 0)
  2216. continue; /* reject duplicate JFIF */
  2217. if (dstinfo->write_Adobe_marker &&
  2218. marker->marker == JPEG_APP0 + 14 &&
  2219. marker->data_length >= 5 &&
  2220. marker->data[0] == 0x41 &&
  2221. marker->data[1] == 0x64 &&
  2222. marker->data[2] == 0x6F &&
  2223. marker->data[3] == 0x62 &&
  2224. marker->data[4] == 0x65)
  2225. continue; /* reject duplicate Adobe */
  2226. jpeg_write_marker(dstinfo, marker->marker,
  2227. marker->data, marker->data_length);
  2228. }
  2229. }