transupp.c 86 KB

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