PageRenderTime 96ms CodeModel.GetById 15ms app.highlight 69ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/LibMNG/libmng_object_prc.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1749 lines | 1353 code | 180 blank | 216 comment | 315 complexity | d56ffb7f9062f3e156cdb829c2ad50c8 MD5 | raw file
   1/* ************************************************************************** */
   2/* *             For conditions of distribution and use,                    * */
   3/* *                see copyright notice in libmng.h                        * */
   4/* ************************************************************************** */
   5/* *                                                                        * */
   6/* * project   : libmng                                                     * */
   7/* * file      : libmng_object_prc.c       copyright (c) 2000-2007 G.Juyn   * */
   8/* * version   : 1.0.10                                                     * */
   9/* *                                                                        * */
  10/* * purpose   : Object processing routines (implementation)                * */
  11/* *                                                                        * */
  12/* * author    : G.Juyn                                                     * */
  13/* *                                                                        * */
  14/* * comment   : implementation of the internal object processing routines  * */
  15/* *                                                                        * */
  16/* * changes   : 0.5.1 - 05/08/2000 - G.Juyn                                * */
  17/* *             - changed strict-ANSI stuff                                * */
  18/* *             0.5.1 - 05/12/2000 - G.Juyn                                * */
  19/* *             - changed trace to macro for callback error-reporting      * */
  20/* *                                                                        * */
  21/* *             0.5.2 - 05/20/2000 - G.Juyn                                * */
  22/* *             - fixed to support JNG objects                             * */
  23/* *             0.5.2 - 05/24/2000 - G.Juyn                                * */
  24/* *             - added support for global color-chunks in animation       * */
  25/* *             - added support for global PLTE,tRNS,bKGD in animation     * */
  26/* *             - added SAVE & SEEK animation objects                      * */
  27/* *             0.5.2 - 05/29/2000 - G.Juyn                                * */
  28/* *             - added initialization of framenr/layernr/playtime         * */
  29/* *             - changed ani_object create routines not to return the     * */
  30/* *               created object (wasn't necessary)                        * */
  31/* *             0.5.2 - 05/30/2000 - G.Juyn                                * */
  32/* *             - added object promotion routine (PROM handling)           * */
  33/* *             - added ani-object routines for delta-image processing     * */
  34/* *             - added compression/filter/interlace fields to             * */
  35/* *               object-buffer for delta-image processing                 * */
  36/* *                                                                        * */
  37/* *             0.5.3 - 06/17/2000 - G.Juyn                                * */
  38/* *             - changed support for delta-image processing               * */
  39/* *             0.5.3 - 06/20/2000 - G.Juyn                                * */
  40/* *             - fixed some small things (as precaution)                  * */
  41/* *             0.5.3 - 06/21/2000 - G.Juyn                                * */
  42/* *             - added processing of PLTE/tRNS & color-info for           * */
  43/* *               delta-images in the ani_objects chain                    * */
  44/* *             0.5.3 - 06/22/2000 - G.Juyn                                * */
  45/* *             - added support for PPLT chunk                             * */
  46/* *                                                                        * */
  47/* *             0.9.1 - 07/07/2000 - G.Juyn                                * */
  48/* *             - added support for freeze/restart/resume & go_xxxx        * */
  49/* *             0.9.1 - 07/16/2000 - G.Juyn                                * */
  50/* *             - fixed support for mng_display() after mng_read()         * */
  51/* *                                                                        * */
  52/* *             0.9.2 - 07/29/2000 - G.Juyn                                * */
  53/* *             - fixed small bugs in display processing                   * */
  54/* *             0.9.2 - 08/05/2000 - G.Juyn                                * */
  55/* *             - changed file-prefixes                                    * */
  56/* *                                                                        * */
  57/* *             0.9.3 - 08/07/2000 - G.Juyn                                * */
  58/* *             - B111300 - fixup for improved portability                 * */
  59/* *             0.9.3 - 08/26/2000 - G.Juyn                                * */
  60/* *             - added MAGN chunk                                         * */
  61/* *             0.9.3 - 09/10/2000 - G.Juyn                                * */
  62/* *             - fixed DEFI behavior                                      * */
  63/* *             0.9.3 - 10/17/2000 - G.Juyn                                * */
  64/* *             - added valid-flag to stored objects for read() / display()* */
  65/* *             - added routine to discard "invalid" objects               * */
  66/* *             0.9.3 - 10/18/2000 - G.Juyn                                * */
  67/* *             - fixed delta-processing behavior                          * */
  68/* *             0.9.3 - 10/19/2000 - G.Juyn                                * */
  69/* *             - added storage for pixel-/alpha-sampledepth for delta's   * */
  70/* *                                                                        * */
  71/* *             0.9.4 -  1/18/2001 - G.Juyn                                * */
  72/* *             - removed "old" MAGN methods 3 & 4                         * */
  73/* *             - added "new" MAGN methods 3, 4 & 5                        * */
  74/* *                                                                        * */
  75/* *             0.9.5 -  1/22/2001 - G.Juyn                                * */
  76/* *             - B129681 - fixed compiler warnings SGI/Irix               * */
  77/* *                                                                        * */
  78/* *             1.0.2 - 06/23/2001 - G.Juyn                                * */
  79/* *             - added optimization option for MNG-video playback         * */
  80/* *                                                                        * */
  81/* *             1.0.5 - 08/15/2002 - G.Juyn                                * */
  82/* *             - completed PROM support                                   * */
  83/* *             1.0.5 - 08/16/2002 - G.Juyn                                * */
  84/* *             - completed MAGN support (16-bit functions)                * */
  85/* *             1.0.5 - 08/19/2002 - G.Juyn                                * */
  86/* *             - B597134 - libmng pollutes the linker namespace           * */
  87/* *             1.0.5 - 09/13/2002 - G.Juyn                                * */
  88/* *             - fixed read/write of MAGN chunk                           * */
  89/* *             1.0.5 - 09/15/2002 - G.Juyn                                * */
  90/* *             - added event handling for dynamic MNG                     * */
  91/* *             1.0.5 - 09/20/2002 - G.Juyn                                * */
  92/* *             - added support for PAST                                   * */
  93/* *             1.0.5 - 09/23/2002 - G.Juyn                                * */
  94/* *             - fixed reset_object_detail to clear old buffer            * */
  95/* *             - added in-memory color-correction of abstract images      * */
  96/* *             1.0.5 - 10/05/2002 - G.Juyn                                * */
  97/* *             - fixed problem with cloned objects marked as invalid      * */
  98/* *             - fixed problem cloning frozen object_buffers              * */
  99/* *             1.0.5 - 10/07/2002 - G.Juyn                                * */
 100/* *             - fixed DISC support                                       * */
 101/* *             1.0.5 - 11/04/2002 - G.Juyn                                * */
 102/* *             - fixed goframe/golayer/gotime processing                  * */
 103/* *             1.0.5 - 11/07/2002 - G.Juyn                                * */
 104/* *             - fixed magnification bug with object 0                    * */
 105/* *             1.0.5 - 01/19/2003 - G.Juyn                                * */
 106/* *             - B664911 - fixed buffer overflow during init              * */
 107/* *                                                                        * */
 108/* *             1.0.6 - 04/19/2003 - G.Juyn                                * */
 109/* *             - fixed problem with infinite loops during readdisplay()   * */
 110/* *             1.0.6 - 05/25/2003 - G.R-P                                 * */
 111/* *             - added MNG_SKIPCHUNK_cHNK footprint optimizations         * */
 112/* *             1.0.6 - 06/09/2003 - G. R-P                                * */
 113/* *             - added conditionals around 8-bit magn routines            * */
 114/* *             1.0.6 - 07/07/2003 - G.R-P                                 * */
 115/* *             - added conditionals around some JNG-supporting code       * */
 116/* *             - removed conditionals around 8-bit magn routines          * */
 117/* *             - added conditionals around delta-png and 16-bit code      * */
 118/* *             1.0.6 - 07/14/2003 - G.R-P                                 * */
 119/* *             - added MNG_NO_LOOP_SIGNALS_SUPPORTED conditional          * */
 120/* *             1.0.6 - 07/29/2003 - G.Juyn                                * */
 121/* *             - fixed invalid test in promote_imageobject                * */
 122/* *             1.0.6 - 07/29/2003 - G.R-P.                                * */
 123/* *             - added conditionals around PAST chunk support             * */
 124/* *             1.0.6 - 08/17/2003 - G.R-P.                                * */
 125/* *             - added conditionals around MAGN chunk support             * */
 126/* *                                                                        * */
 127/* *             1.0.7 - 03/21/2004 - G.Juyn                                * */
 128/* *             - fixed some 64-bit platform compiler warnings             * */
 129/* *                                                                        * */
 130/* *             1.0.9 - 10/10/2004 - G.R-P.                                * */
 131/* *             - added MNG_NO_1_2_4BIT_SUPPORT support                    * */
 132/* *             1.0.9 - 12/05/2004 - G.Juyn                                * */
 133/* *             - added conditional MNG_OPTIMIZE_OBJCLEANUP                * */
 134/* *             1.0.9 - 12/11/2004 - G.Juyn                                * */
 135/* *             - added conditional MNG_OPTIMIZE_DISPLAYCALLS              * */
 136/* *             1.0.9 - 12/31/2004 - G.R-P.                                * */
 137/* *             - fixed warnings about possible uninitialized pointers     * */
 138/* *             1.0.9 - 01/02/2005 - G.Juyn                                * */
 139/* *             - fixing some compiler-warnings                            * */
 140/* *                                                                        * */
 141/* *             1.0.10 - 02/07/2005 - G.Juyn                               * */
 142/* *             - fixed some compiler-warnings                             * */
 143/* *             1.0.10 - 07/30/2005 - G.Juyn                               * */
 144/* *             - fixed problem with CLON object during readdisplay()      * */
 145/* *             1.0.10 - 04/08/2007 - G.Juyn                               * */
 146/* *             - added support for mPNG proposal                          * */
 147/* *             1.0.10 - 04/12/2007 - G.Juyn                               * */
 148/* *             - added support for ANG proposal                           * */
 149/* *                                                                        * */
 150/* ************************************************************************** */
 151
 152#include "libmng.h"
 153#include "libmng_data.h"
 154#include "libmng_error.h"
 155#include "libmng_trace.h"
 156#ifdef __BORLANDC__
 157#pragma hdrstop
 158#endif
 159#include "libmng_memory.h"
 160#include "libmng_chunks.h"
 161#include "libmng_objects.h"
 162#include "libmng_display.h"
 163#include "libmng_pixels.h"
 164#include "libmng_object_prc.h"
 165#include "libmng_cms.h"
 166
 167#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
 168#pragma option -A                      /* force ANSI-C */
 169#endif
 170
 171/* ************************************************************************** */
 172
 173#ifdef MNG_INCLUDE_DISPLAY_PROCS
 174
 175/* ************************************************************************** */
 176/* *                                                                        * */
 177/* * Generic object routines                                                * */
 178/* *                                                                        * */
 179/* ************************************************************************** */
 180
 181mng_retcode mng_drop_invalid_objects (mng_datap pData)
 182{
 183  mng_objectp       pObject;
 184  mng_objectp       pNext;
 185  mng_cleanupobject fCleanup;
 186
 187#ifdef MNG_SUPPORT_TRACE
 188  MNG_TRACE (pData, MNG_FN_DROP_INVALID_OBJECTS, MNG_LC_START);
 189#endif
 190
 191  pObject = pData->pFirstimgobj;       /* get first stored image-object (if any) */
 192
 193  while (pObject)                      /* more objects to check ? */
 194  {
 195    pNext = ((mng_object_headerp)pObject)->pNext;
 196                                       /* invalid ? */
 197    if (!((mng_imagep)pObject)->bValid)
 198    {                                  /* call appropriate cleanup */
 199      fCleanup = ((mng_object_headerp)pObject)->fCleanup;
 200      fCleanup (pData, pObject);
 201    }
 202
 203    pObject = pNext;                   /* neeeext */
 204  }
 205
 206#ifdef MNG_SUPPORT_TRACE
 207  MNG_TRACE (pData, MNG_FN_DROP_INVALID_OBJECTS, MNG_LC_END);
 208#endif
 209
 210  return MNG_NOERROR;
 211}
 212
 213/* ************************************************************************** */
 214
 215#ifdef MNG_OPTIMIZE_OBJCLEANUP
 216MNG_LOCAL mng_retcode create_obj_general (mng_datap          pData,
 217                                          mng_size_t         iObjsize,
 218                                          mng_cleanupobject  fCleanup,
 219                                          mng_processobject  fProcess,
 220                                          mng_ptr            *ppObject)
 221{
 222  mng_object_headerp pWork;
 223
 224  MNG_ALLOC (pData, pWork, iObjsize);
 225
 226  pWork->fCleanup = fCleanup;
 227  pWork->fProcess = fProcess;
 228  pWork->iObjsize = iObjsize;
 229  *ppObject       = (mng_ptr)pWork;
 230
 231  return MNG_NOERROR;
 232}
 233
 234/* ************************************************************************** */
 235
 236MNG_LOCAL mng_retcode mng_free_obj_general (mng_datap   pData,
 237                                            mng_objectp pObject)
 238{
 239  MNG_FREEX (pData, pObject, ((mng_object_headerp)pObject)->iObjsize);
 240  return MNG_NOERROR;
 241}
 242#endif
 243
 244/* ************************************************************************** */
 245/* *                                                                        * */
 246/* * Image-data-object routines                                             * */
 247/* *                                                                        * */
 248/* * these handle the "object buffer" as defined by the MNG specification   * */
 249/* *                                                                        * */
 250/* ************************************************************************** */
 251
 252mng_retcode mng_create_imagedataobject (mng_datap      pData,
 253                                        mng_bool       bConcrete,
 254                                        mng_bool       bViewable,
 255                                        mng_uint32     iWidth,
 256                                        mng_uint32     iHeight,
 257                                        mng_uint8      iBitdepth,
 258                                        mng_uint8      iColortype,
 259                                        mng_uint8      iCompression,
 260                                        mng_uint8      iFilter,
 261                                        mng_uint8      iInterlace,
 262                                        mng_imagedatap *ppObject)
 263{
 264  mng_imagedatap pImagedata;
 265  mng_uint32 iSamplesize = 0;
 266
 267#ifdef MNG_SUPPORT_TRACE
 268  MNG_TRACE (pData, MNG_FN_CREATE_IMGDATAOBJECT, MNG_LC_START);
 269#endif
 270                                       /* get a buffer */
 271#ifdef MNG_OPTIMIZE_OBJCLEANUP
 272  {
 273    mng_ptr pTemp;
 274    mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_imagedata),
 275                                               (mng_cleanupobject)mng_free_imagedataobject,
 276                                               MNG_NULL, &pTemp);
 277    if (iRetcode)
 278      return iRetcode;
 279    pImagedata = (mng_imagedatap)pTemp;
 280  }
 281#else
 282  MNG_ALLOC (pData, pImagedata, sizeof (mng_imagedata));
 283                                       /* fill the appropriate fields */
 284  pImagedata->sHeader.fCleanup   = (mng_cleanupobject)mng_free_imagedataobject;
 285  pImagedata->sHeader.fProcess   = MNG_NULL;
 286#endif
 287  pImagedata->iRefcount          = 1;
 288  pImagedata->bFrozen            = MNG_FALSE;
 289  pImagedata->bConcrete          = bConcrete;
 290  pImagedata->bViewable          = bViewable;
 291  pImagedata->iWidth             = iWidth;
 292  pImagedata->iHeight            = iHeight;
 293  pImagedata->iBitdepth          = iBitdepth;
 294  pImagedata->iColortype         = iColortype;
 295  pImagedata->iCompression       = iCompression;
 296  pImagedata->iFilter            = iFilter;
 297  pImagedata->iInterlace         = iInterlace;
 298  pImagedata->bCorrected         = MNG_FALSE;
 299  pImagedata->iAlphabitdepth     = 0;
 300  pImagedata->iJHDRcompression   = 0;
 301  pImagedata->iJHDRinterlace     = 0;
 302  pImagedata->iPixelsampledepth  = iBitdepth;
 303  pImagedata->iAlphasampledepth  = iBitdepth;
 304                                       /* determine samplesize from color_type/bit_depth */
 305  switch (iColortype)                  /* for < 8-bit samples we just reserve 8 bits */
 306  {
 307    case  0  : ;                       /* gray */
 308    case  8  : {                       /* JPEG gray */
 309#ifndef MNG_NO_16BIT_SUPPORT
 310                 if (iBitdepth > 8)
 311                   iSamplesize = 2;
 312                 else
 313#endif
 314                   iSamplesize = 1;
 315
 316                 break;
 317               }
 318    case  2  : ;                       /* rgb */
 319    case 10  : {                       /* JPEG rgb */
 320#ifndef MNG_NO_16BIT_SUPPORT
 321                 if (iBitdepth > 8)
 322                   iSamplesize = 6;
 323                 else
 324#endif
 325                   iSamplesize = 3;
 326
 327                 break;
 328               }
 329    case  3  : {                       /* indexed */
 330                 iSamplesize = 1;
 331                 break;
 332               }
 333    case  4  : ;                       /* gray+alpha */
 334    case 12  : {                       /* JPEG gray+alpha */
 335#ifndef MNG_NO_16BIT_SUPPORT
 336                 if (iBitdepth > 8)
 337                   iSamplesize = 4;
 338                 else
 339#endif
 340                   iSamplesize = 2;
 341
 342                 break;
 343               }
 344    case  6  : ;                       /* rgb+alpha */
 345    case 14  : {                       /* JPEG rgb+alpha */
 346#ifndef MNG_NO_16BIT_SUPPORT
 347                 if (iBitdepth > 8)
 348                   iSamplesize = 8;
 349                 else
 350#endif
 351                   iSamplesize = 4;
 352
 353                 break;
 354               }
 355  }
 356                                       /* make sure we remember all this */
 357  pImagedata->iSamplesize  = iSamplesize;
 358  pImagedata->iRowsize     = iSamplesize * iWidth;
 359  pImagedata->iImgdatasize = pImagedata->iRowsize * iHeight;
 360
 361  if (pImagedata->iImgdatasize)        /* need a buffer ? */
 362  {                                    /* so allocate it */
 363    MNG_ALLOCX (pData, pImagedata->pImgdata, pImagedata->iImgdatasize);
 364
 365    if (!pImagedata->pImgdata)         /* enough memory ? */
 366    {
 367      MNG_FREEX (pData, pImagedata, sizeof (mng_imagedata));
 368      MNG_ERROR (pData, MNG_OUTOFMEMORY);
 369    }
 370  }
 371                                       /* check global stuff */
 372  pImagedata->bHasGAMA           = pData->bHasglobalGAMA;
 373#ifndef MNG_SKIPCHUNK_cHRM
 374  pImagedata->bHasCHRM           = pData->bHasglobalCHRM;
 375#endif
 376  pImagedata->bHasSRGB           = pData->bHasglobalSRGB;
 377#ifndef MNG_SKIPCHUNK_iCCP
 378  pImagedata->bHasICCP           = pData->bHasglobalICCP;
 379#endif
 380#ifndef MNG_SKIPCHUNK_bKGD
 381  pImagedata->bHasBKGD           = pData->bHasglobalBKGD;
 382#endif
 383
 384  if (pData->bHasglobalGAMA)           /* global gAMA present ? */
 385    pImagedata->iGamma           = pData->iGlobalGamma;
 386
 387#ifndef MNG_SKIPCHUNK_cHRM
 388  if (pData->bHasglobalCHRM)           /* global cHRM present ? */
 389  {
 390    pImagedata->iWhitepointx     = pData->iGlobalWhitepointx;
 391    pImagedata->iWhitepointy     = pData->iGlobalWhitepointy;
 392    pImagedata->iPrimaryredx     = pData->iGlobalPrimaryredx;
 393    pImagedata->iPrimaryredy     = pData->iGlobalPrimaryredy;
 394    pImagedata->iPrimarygreenx   = pData->iGlobalPrimarygreenx;
 395    pImagedata->iPrimarygreeny   = pData->iGlobalPrimarygreeny;
 396    pImagedata->iPrimarybluex    = pData->iGlobalPrimarybluex;
 397    pImagedata->iPrimarybluey    = pData->iGlobalPrimarybluey;
 398  }
 399#endif
 400
 401  if (pData->bHasglobalSRGB)           /* glbal sRGB present ? */
 402    pImagedata->iRenderingintent = pData->iGlobalRendintent;
 403
 404#ifndef MNG_SKIPCHUNK_iCCP
 405  if (pData->bHasglobalICCP)           /* glbal iCCP present ? */
 406  {
 407    pImagedata->iProfilesize     = pData->iGlobalProfilesize;
 408
 409    if (pImagedata->iProfilesize)
 410    {
 411      MNG_ALLOCX (pData, pImagedata->pProfile, pImagedata->iProfilesize);
 412
 413      if (!pImagedata->pProfile)       /* enough memory ? */
 414      {
 415        MNG_FREEX (pData, pImagedata->pImgdata, pImagedata->iImgdatasize);
 416        MNG_FREEX (pData, pImagedata, sizeof (mng_imagedata));
 417        MNG_ERROR (pData, MNG_OUTOFMEMORY);
 418      }
 419
 420      MNG_COPY  (pImagedata->pProfile, pData->pGlobalProfile, pImagedata->iProfilesize);
 421    }
 422  }
 423#endif
 424
 425#ifndef MNG_SKIPCHUNK_bKGD
 426  if (pData->bHasglobalBKGD)           /* global bKGD present ? */
 427  {
 428    pImagedata->iBKGDred         = pData->iGlobalBKGDred;
 429    pImagedata->iBKGDgreen       = pData->iGlobalBKGDgreen;
 430    pImagedata->iBKGDblue        = pData->iGlobalBKGDblue;
 431  }
 432#endif
 433
 434  *ppObject = pImagedata;              /* return it */
 435
 436#ifdef MNG_SUPPORT_TRACE
 437  MNG_TRACE (pData, MNG_FN_CREATE_IMGDATAOBJECT, MNG_LC_END);
 438#endif
 439
 440  return MNG_NOERROR;
 441}
 442
 443/* ************************************************************************** */
 444
 445mng_retcode mng_free_imagedataobject   (mng_datap      pData,
 446                                        mng_imagedatap pImagedata)
 447{
 448#ifdef MNG_SUPPORT_TRACE
 449  MNG_TRACE (pData, MNG_FN_FREE_IMGDATAOBJECT, MNG_LC_START);
 450#endif
 451
 452  if (pImagedata->iRefcount)           /* decrease reference count */
 453    pImagedata->iRefcount--;
 454
 455  if (!pImagedata->iRefcount)          /* reached zero ? */
 456  {
 457#ifndef MNG_SKIPCHUNK_iCCP
 458    if (pImagedata->iProfilesize)      /* stored an iCCP profile ? */
 459      MNG_FREEX (pData, pImagedata->pProfile, pImagedata->iProfilesize);
 460#endif
 461    if (pImagedata->iImgdatasize)      /* sample-buffer present ? */
 462      MNG_FREEX (pData, pImagedata->pImgdata, pImagedata->iImgdatasize);
 463                                       /* drop the buffer */
 464    MNG_FREEX (pData, pImagedata, sizeof (mng_imagedata));
 465  }
 466
 467#ifdef MNG_SUPPORT_TRACE
 468  MNG_TRACE (pData, MNG_FN_FREE_IMGDATAOBJECT, MNG_LC_END);
 469#endif
 470
 471  return MNG_NOERROR;
 472}
 473
 474/* ************************************************************************** */
 475
 476mng_retcode mng_clone_imagedataobject  (mng_datap      pData,
 477                                        mng_bool       bConcrete,
 478                                        mng_imagedatap pSource,
 479                                        mng_imagedatap *ppClone)
 480{
 481  mng_imagedatap pNewdata;
 482
 483#ifdef MNG_SUPPORT_TRACE
 484  MNG_TRACE (pData, MNG_FN_CLONE_IMGDATAOBJECT, MNG_LC_START);
 485#endif
 486                                       /* get a buffer */
 487  MNG_ALLOC (pData, pNewdata, sizeof (mng_imagedata));
 488                                       /* blatently copy the original buffer */
 489  MNG_COPY (pNewdata, pSource, sizeof (mng_imagedata));
 490
 491  pNewdata->iRefcount = 1;             /* only the reference count */
 492  pNewdata->bConcrete = bConcrete;     /* and concrete-flag are different */
 493  pNewdata->bFrozen   = MNG_FALSE;
 494
 495  if (pNewdata->iImgdatasize)          /* sample buffer present ? */
 496  {
 497    MNG_ALLOCX (pData, pNewdata->pImgdata, pNewdata->iImgdatasize);
 498
 499    if (!pNewdata->pImgdata)           /* not enough memory ? */
 500    {
 501      MNG_FREEX (pData, pNewdata, sizeof (mng_imagedata));
 502      MNG_ERROR (pData, MNG_OUTOFMEMORY);
 503    }
 504                                       /* make a copy */
 505    MNG_COPY (pNewdata->pImgdata, pSource->pImgdata, pNewdata->iImgdatasize);
 506  }
 507
 508#ifndef MNG_SKIPCHUNK_iCCP
 509  if (pNewdata->iProfilesize)          /* iCCP profile present ? */
 510  {
 511    MNG_ALLOCX (pData, pNewdata->pProfile, pNewdata->iProfilesize);
 512
 513    if (!pNewdata->pProfile)           /* enough memory ? */
 514    {
 515      MNG_FREEX (pData, pNewdata, sizeof (mng_imagedata));
 516      MNG_ERROR (pData, MNG_OUTOFMEMORY);
 517    }
 518                                       /* make a copy */
 519    MNG_COPY (pNewdata->pProfile, pSource->pProfile, pNewdata->iProfilesize);
 520  }
 521#endif
 522
 523  *ppClone = pNewdata;                 /* return the clone */
 524
 525#ifdef MNG_SUPPORT_TRACE
 526  MNG_TRACE (pData, MNG_FN_CLONE_IMGDATAOBJECT, MNG_LC_END);
 527#endif
 528
 529  return MNG_NOERROR;
 530}
 531
 532/* ************************************************************************** */
 533/* *                                                                        * */
 534/* * Image-object routines                                                  * */
 535/* *                                                                        * */
 536/* * these handle the "object" as defined by the MNG specification          * */
 537/* *                                                                        * */
 538/* ************************************************************************** */
 539
 540mng_retcode mng_create_imageobject (mng_datap  pData,
 541                                    mng_uint16 iId,
 542                                    mng_bool   bConcrete,
 543                                    mng_bool   bVisible,
 544                                    mng_bool   bViewable,
 545                                    mng_uint32 iWidth,
 546                                    mng_uint32 iHeight,
 547                                    mng_uint8  iBitdepth,
 548                                    mng_uint8  iColortype,
 549                                    mng_uint8  iCompression,
 550                                    mng_uint8  iFilter,
 551                                    mng_uint8  iInterlace,
 552                                    mng_int32  iPosx,
 553                                    mng_int32  iPosy,
 554                                    mng_bool   bClipped,
 555                                    mng_int32  iClipl,
 556                                    mng_int32  iClipr,
 557                                    mng_int32  iClipt,
 558                                    mng_int32  iClipb,
 559                                    mng_imagep *ppObject)
 560{
 561  mng_imagep     pImage;
 562  mng_imagep     pPrev, pNext;
 563  mng_retcode    iRetcode;
 564  mng_imagedatap pImgbuf;
 565
 566#ifdef MNG_SUPPORT_TRACE
 567  MNG_TRACE (pData, MNG_FN_CREATE_IMGOBJECT, MNG_LC_START);
 568#endif
 569                                       /* get a buffer */
 570  MNG_ALLOC (pData, pImage, sizeof (mng_image));
 571                                       /* now get a new "object buffer" */
 572  iRetcode = mng_create_imagedataobject (pData, bConcrete, bViewable,
 573                                         iWidth, iHeight, iBitdepth, iColortype,
 574                                         iCompression, iFilter, iInterlace,
 575                                         &pImgbuf);
 576
 577  if (iRetcode)                        /* on error bail out */
 578  {
 579    MNG_FREEX (pData, pImage, sizeof (mng_image));
 580    return iRetcode;
 581  }
 582                                       /* fill the appropriate fields */
 583  pImage->sHeader.fCleanup = (mng_cleanupobject)mng_free_imageobject;
 584  pImage->sHeader.fProcess = MNG_NULL;
 585#ifdef MNG_OPTIMIZE_OBJCLEANUP
 586  pImage->sHeader.iObjsize = sizeof (mng_image);
 587#endif
 588  pImage->iId              = iId;
 589  pImage->bFrozen          = MNG_FALSE;
 590  pImage->bVisible         = bVisible;
 591  pImage->bViewable        = bViewable;
 592  pImage->bValid           = (mng_bool)((pData->bDisplaying) &&
 593                                        ((pData->bRunning) || (pData->bSearching)) &&
 594                                        (!pData->bFreezing));
 595  pImage->iPosx            = iPosx;
 596  pImage->iPosy            = iPosy;
 597  pImage->bClipped         = bClipped;
 598  pImage->iClipl           = iClipl;
 599  pImage->iClipr           = iClipr;
 600  pImage->iClipt           = iClipt;
 601  pImage->iClipb           = iClipb;
 602#ifndef MNG_SKIPCHUNK_MAGN
 603  pImage->iMAGN_MethodX    = 0;
 604  pImage->iMAGN_MethodY    = 0;
 605  pImage->iMAGN_MX         = 0;
 606  pImage->iMAGN_MY         = 0;
 607  pImage->iMAGN_ML         = 0;
 608  pImage->iMAGN_MR         = 0;
 609  pImage->iMAGN_MT         = 0;
 610  pImage->iMAGN_MB         = 0;
 611#endif
 612#ifndef MNG_SKIPCHUNK_PAST
 613  pImage->iPastx           = 0;
 614  pImage->iPasty           = 0;
 615#endif
 616  pImage->pImgbuf          = pImgbuf;
 617
 618  if (iId)                             /* only if not object 0 ! */
 619  {                                    /* find previous lower object-id */
 620    pPrev = (mng_imagep)pData->pLastimgobj;
 621
 622    while ((pPrev) && (pPrev->iId > iId))
 623      pPrev = (mng_imagep)pPrev->sHeader.pPrev;
 624
 625    if (pPrev)                         /* found it ? */
 626    {
 627      pImage->sHeader.pPrev = pPrev;   /* than link it in place */
 628      pImage->sHeader.pNext = pPrev->sHeader.pNext;
 629      pPrev->sHeader.pNext  = pImage;
 630    }
 631    else                               /* if not found, it becomes the first ! */
 632    {
 633      pImage->sHeader.pNext = pData->pFirstimgobj;
 634      pData->pFirstimgobj   = pImage;
 635    }
 636
 637    pNext                   = (mng_imagep)pImage->sHeader.pNext;
 638
 639    if (pNext)
 640      pNext->sHeader.pPrev  = pImage;
 641    else
 642      pData->pLastimgobj    = pImage;
 643    
 644  }  
 645
 646  *ppObject = pImage;                  /* and return the new buffer */
 647
 648#ifdef MNG_SUPPORT_TRACE
 649  MNG_TRACE (pData, MNG_FN_CREATE_IMGOBJECT, MNG_LC_END);
 650#endif
 651
 652  return MNG_NOERROR;                  /* okido */
 653}
 654
 655/* ************************************************************************** */
 656
 657mng_retcode mng_free_imageobject (mng_datap  pData,
 658                                  mng_imagep pImage)
 659{
 660  mng_retcode    iRetcode;
 661  mng_imagep     pPrev   = pImage->sHeader.pPrev;
 662  mng_imagep     pNext   = pImage->sHeader.pNext;
 663  mng_imagedatap pImgbuf = pImage->pImgbuf;
 664
 665#ifdef MNG_SUPPORT_TRACE
 666  MNG_TRACE (pData, MNG_FN_FREE_IMGOBJECT, MNG_LC_START);
 667#endif
 668
 669  if (pImage->iId)                     /* not for object 0 */
 670  {
 671    if (pPrev)                         /* unlink from the list first ! */
 672      pPrev->sHeader.pNext = pImage->sHeader.pNext;
 673    else
 674      pData->pFirstimgobj  = pImage->sHeader.pNext;
 675
 676    if (pNext)
 677      pNext->sHeader.pPrev = pImage->sHeader.pPrev;
 678    else
 679      pData->pLastimgobj   = pImage->sHeader.pPrev;
 680
 681  }
 682                                       /* unlink the image-data buffer */
 683  iRetcode = mng_free_imagedataobject (pData, pImgbuf);
 684                                       /* drop its own buffer */
 685  MNG_FREEX (pData, pImage, sizeof (mng_image));
 686
 687#ifdef MNG_SUPPORT_TRACE
 688  MNG_TRACE (pData, MNG_FN_FREE_IMGOBJECT, MNG_LC_END);
 689#endif
 690
 691  return iRetcode;
 692}
 693
 694/* ************************************************************************** */
 695
 696mng_imagep mng_find_imageobject (mng_datap  pData,
 697                                 mng_uint16 iId)
 698{
 699  mng_imagep pImage = (mng_imagep)pData->pFirstimgobj;
 700
 701#ifdef MNG_SUPPORT_TRACE
 702  MNG_TRACEX (pData, MNG_FN_FIND_IMGOBJECT, MNG_LC_START);
 703#endif
 704                                       /* look up the right id */
 705  while ((pImage) && (pImage->iId != iId))
 706    pImage = (mng_imagep)pImage->sHeader.pNext;
 707
 708#ifdef MNG_INCLUDE_MPNG_PROPOSAL
 709  if ((!pImage) && (pData->eImagetype == mng_it_mpng))
 710    pImage = pData->pObjzero;
 711#endif
 712
 713#ifdef MNG_SUPPORT_TRACE
 714  MNG_TRACEX (pData, MNG_FN_FIND_IMGOBJECT, MNG_LC_END);
 715#endif
 716
 717  return pImage;
 718}
 719
 720/* ************************************************************************** */
 721
 722mng_retcode mng_clone_imageobject (mng_datap  pData,
 723                                   mng_uint16 iId,
 724                                   mng_bool   bPartial,
 725                                   mng_bool   bVisible,
 726                                   mng_bool   bAbstract,
 727                                   mng_bool   bHasloca,
 728                                   mng_uint8  iLocationtype,
 729                                   mng_int32  iLocationx,
 730                                   mng_int32  iLocationy,
 731                                   mng_imagep pSource,
 732                                   mng_imagep *ppClone)
 733{
 734  mng_imagep     pNew;
 735  mng_imagep     pPrev, pNext;
 736  mng_retcode    iRetcode;
 737  mng_imagedatap pImgbuf;
 738
 739#ifdef MNG_SUPPORT_TRACE
 740  MNG_TRACE (pData, MNG_FN_CLONE_IMGOBJECT, MNG_LC_START);
 741#endif
 742
 743#ifndef MNG_SKIPCHUNK_MAGN
 744  if ((pSource->iId) &&                /* needs magnification ? */
 745      ((pSource->iMAGN_MethodX) || (pSource->iMAGN_MethodY)))
 746  {
 747    iRetcode = mng_magnify_imageobject (pData, pSource);
 748
 749    if (iRetcode)                      /* on error bail out */
 750      return iRetcode;
 751  }
 752#endif
 753                                       /* get a buffer */
 754#ifdef MNG_OPTIMIZE_OBJCLEANUP
 755  {
 756    mng_ptr     pTemp;
 757    mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_image),
 758                                               (mng_cleanupobject)mng_free_imageobject,
 759                                               MNG_NULL, &pTemp);
 760    if (iRetcode)
 761      return iRetcode;
 762    pNew = (mng_imagep)pTemp;
 763  }
 764#else
 765  MNG_ALLOC (pData, pNew, sizeof (mng_image));
 766                                       /* fill or copy the appropriate fields */
 767  pNew->sHeader.fCleanup = (mng_cleanupobject)mng_free_imageobject;
 768  pNew->sHeader.fProcess = MNG_NULL;
 769#endif
 770  pNew->iId              = iId;
 771  pNew->bFrozen          = MNG_FALSE;
 772  pNew->bVisible         = bVisible;
 773  pNew->bViewable        = pSource->bViewable;
 774  pNew->bValid           = MNG_TRUE;
 775
 776  if (bHasloca)                        /* location info available ? */
 777  {
 778    if (iLocationtype == 0)            /* absolute position ? */
 779    {
 780      pNew->iPosx        = iLocationx;
 781      pNew->iPosy        = iLocationy;
 782    }
 783    else                               /* relative */
 784    {
 785      pNew->iPosx        = pSource->iPosx + iLocationx;
 786      pNew->iPosy        = pSource->iPosy + iLocationy;
 787    }
 788  }
 789  else                                 /* copy from source */
 790  {
 791    pNew->iPosx          = pSource->iPosx;
 792    pNew->iPosy          = pSource->iPosy;
 793  }
 794                                       /* copy clipping info */
 795  pNew->bClipped         = pSource->bClipped;
 796  pNew->iClipl           = pSource->iClipl;
 797  pNew->iClipr           = pSource->iClipr;
 798  pNew->iClipt           = pSource->iClipt;
 799  pNew->iClipb           = pSource->iClipb;
 800#ifndef MNG_SKIPCHUNK_MAGN
 801                                       /* copy magnification info */
 802/*  pNew->iMAGN_MethodX    = pSource->iMAGN_MethodX;     LET'S NOT !!!!!!
 803  pNew->iMAGN_MethodY    = pSource->iMAGN_MethodY;
 804  pNew->iMAGN_MX         = pSource->iMAGN_MX;
 805  pNew->iMAGN_MY         = pSource->iMAGN_MY;
 806  pNew->iMAGN_ML         = pSource->iMAGN_ML;
 807  pNew->iMAGN_MR         = pSource->iMAGN_MR;
 808  pNew->iMAGN_MT         = pSource->iMAGN_MT;
 809  pNew->iMAGN_MB         = pSource->iMAGN_MB; */
 810#endif
 811
 812#ifndef MNG_SKIPCHUNK_PAST
 813  pNew->iPastx           = 0;          /* initialize PAST info */
 814  pNew->iPasty           = 0;
 815#endif
 816
 817  if (iId)                             /* not for object 0 */
 818  {                                    /* find previous lower object-id */
 819    pPrev = (mng_imagep)pData->pLastimgobj;
 820    while ((pPrev) && (pPrev->iId > iId))
 821      pPrev = (mng_imagep)pPrev->sHeader.pPrev;
 822
 823    if (pPrev)                         /* found it ? */
 824    {
 825      pNew->sHeader.pPrev  = pPrev;    /* than link it in place */
 826      pNew->sHeader.pNext  = pPrev->sHeader.pNext;
 827      pPrev->sHeader.pNext = pNew;
 828    }
 829    else                               /* if not found, it becomes the first ! */
 830    {
 831      pNew->sHeader.pNext  = pData->pFirstimgobj;
 832      pData->pFirstimgobj  = pNew;
 833    }
 834
 835    pNext                  = (mng_imagep)pNew->sHeader.pNext;
 836
 837    if (pNext)
 838      pNext->sHeader.pPrev = pNew;
 839    else
 840      pData->pLastimgobj   = pNew;
 841
 842  }
 843
 844  if (bPartial)                        /* partial clone ? */
 845  {
 846    pNew->pImgbuf = pSource->pImgbuf;  /* use the same object buffer */
 847    pNew->pImgbuf->iRefcount++;        /* and increase the reference count */
 848  }
 849  else                                 /* create a full clone ! */
 850  {
 851    mng_bool bConcrete = MNG_FALSE;    /* it's abstract by default (?) */
 852
 853    if (!bAbstract)                    /* determine concreteness from source ? */
 854      bConcrete = pSource->pImgbuf->bConcrete;
 855                                       /* create a full clone ! */
 856    iRetcode = mng_clone_imagedataobject (pData, bConcrete, pSource->pImgbuf, &pImgbuf);
 857
 858    if (iRetcode)                      /* on error bail out */
 859    {
 860      MNG_FREEX (pData, pNew, sizeof (mng_image));
 861      return iRetcode;
 862    }
 863
 864    pNew->pImgbuf = pImgbuf;           /* and remember it */
 865  }
 866
 867  *ppClone = pNew;                     /* return it */
 868
 869#ifdef MNG_SUPPORT_TRACE
 870  MNG_TRACE (pData, MNG_FN_CLONE_IMGOBJECT, MNG_LC_END);
 871#endif
 872
 873  return MNG_NOERROR;
 874}
 875
 876/* ************************************************************************** */
 877
 878mng_retcode mng_renum_imageobject (mng_datap  pData,
 879                                   mng_imagep pSource,
 880                                   mng_uint16 iId,
 881                                   mng_bool   bVisible,
 882                                   mng_bool   bAbstract,
 883                                   mng_bool   bHasloca,
 884                                   mng_uint8  iLocationtype,
 885                                   mng_int32  iLocationx,
 886                                   mng_int32  iLocationy)
 887{
 888  mng_imagep pPrev, pNext;
 889
 890#ifdef MNG_SUPPORT_TRACE
 891  MNG_TRACE (pData, MNG_FN_RENUM_IMGOBJECT, MNG_LC_START);
 892#endif
 893
 894  pSource->bVisible  = bVisible;       /* store the new visibility */
 895
 896  if (bHasloca)                        /* location info available ? */
 897  {
 898    if (iLocationtype == 0)            /* absolute position ? */
 899    {
 900      pSource->iPosx = iLocationx;
 901      pSource->iPosy = iLocationy;
 902    }
 903    else                               /* relative */
 904    {
 905      pSource->iPosx = pSource->iPosx + iLocationx;
 906      pSource->iPosy = pSource->iPosy + iLocationy;
 907    }
 908  }
 909
 910  if (iId)                             /* not for object 0 */
 911  {                                    /* find previous lower object-id */
 912    pPrev = (mng_imagep)pData->pLastimgobj;
 913    while ((pPrev) && (pPrev->iId > iId))
 914      pPrev = (mng_imagep)pPrev->sHeader.pPrev;
 915                                       /* different from current ? */
 916    if (pPrev != (mng_imagep)pSource->sHeader.pPrev)
 917    {
 918      if (pSource->sHeader.pPrev)      /* unlink from current position !! */
 919        ((mng_imagep)pSource->sHeader.pPrev)->sHeader.pNext = pSource->sHeader.pNext;
 920      else
 921        pData->pFirstimgobj                                 = pSource->sHeader.pNext;
 922
 923      if (pSource->sHeader.pNext)
 924        ((mng_imagep)pSource->sHeader.pNext)->sHeader.pPrev = pSource->sHeader.pPrev;
 925      else
 926        pData->pLastimgobj                                  = pSource->sHeader.pPrev;
 927
 928      if (pPrev)                       /* found the previous ? */
 929      {                                /* than link it in place */
 930        pSource->sHeader.pPrev = pPrev;
 931        pSource->sHeader.pNext = pPrev->sHeader.pNext;
 932        pPrev->sHeader.pNext   = pSource;
 933      }
 934      else                             /* if not found, it becomes the first ! */
 935      {
 936        pSource->sHeader.pNext = pData->pFirstimgobj;
 937        pData->pFirstimgobj    = pSource;
 938      }
 939
 940      pNext                    = (mng_imagep)pSource->sHeader.pNext;
 941
 942      if (pNext)
 943        pNext->sHeader.pPrev   = pSource;
 944      else
 945        pData->pLastimgobj     = pSource;
 946
 947    }
 948  }
 949
 950  pSource->iId = iId;                  /* now set the new id! */
 951
 952  if (bAbstract)                       /* force it to abstract ? */
 953    pSource->pImgbuf->bConcrete = MNG_FALSE;
 954
 955#ifdef MNG_SUPPORT_TRACE
 956  MNG_TRACE (pData, MNG_FN_RENUM_IMGOBJECT, MNG_LC_END);
 957#endif
 958
 959  return MNG_NOERROR;
 960}
 961
 962/* ************************************************************************** */
 963
 964mng_retcode mng_reset_object_details (mng_datap  pData,
 965                                      mng_imagep pImage,
 966                                      mng_uint32 iWidth,
 967                                      mng_uint32 iHeight,
 968                                      mng_uint8  iBitdepth,
 969                                      mng_uint8  iColortype,
 970                                      mng_uint8  iCompression,
 971                                      mng_uint8  iFilter,
 972                                      mng_uint8  iInterlace,
 973                                      mng_bool   bResetall)
 974{
 975  mng_imagedatap pBuf  = pImage->pImgbuf;
 976  mng_uint32     iSamplesize = 0;
 977  mng_uint32     iRowsize;
 978  mng_uint32     iImgdatasize;
 979
 980#ifdef MNG_SUPPORT_TRACE
 981  MNG_TRACE (pData, MNG_FN_RESET_OBJECTDETAILS, MNG_LC_START);
 982#endif
 983
 984  pBuf->iWidth         = iWidth;       /* set buffer characteristics */
 985  pBuf->iHeight        = iHeight;
 986  pBuf->iBitdepth      = iBitdepth;
 987  pBuf->iColortype     = iColortype;
 988  pBuf->iCompression   = iCompression;
 989  pBuf->iFilter        = iFilter;
 990  pBuf->iInterlace     = iInterlace;
 991  pBuf->bCorrected     = MNG_FALSE;
 992  pBuf->iAlphabitdepth = 0;
 993                                       /* determine samplesize from color_type/bit_depth */
 994  switch (iColortype)                  /* for < 8-bit samples we just reserve 8 bits */
 995  {
 996    case  0  : ;                       /* gray */
 997    case  8  : {                       /* JPEG gray */
 998#ifndef MNG_NO_16BIT_SUPPORT
 999                 if (iBitdepth > 8)
1000                   iSamplesize = 2;
1001                 else
1002#endif
1003                   iSamplesize = 1;
1004
1005                 break;
1006               }
1007    case  2  : ;                       /* rgb */
1008    case 10  : {                       /* JPEG rgb */
1009#ifndef MNG_NO_16BIT_SUPPORT
1010                 if (iBitdepth > 8)
1011                   iSamplesize = 6;
1012                 else
1013#endif
1014                   iSamplesize = 3;
1015
1016                 break;
1017               }
1018    case  3  : {                       /* indexed */
1019                 iSamplesize = 1;
1020                 break;
1021               }
1022    case  4  : ;                       /* gray+alpha */
1023    case 12  : {                       /* JPEG gray+alpha */
1024#ifndef MNG_NO_16BIT_SUPPORT
1025                 if (iBitdepth > 8)
1026                   iSamplesize = 4;
1027                 else
1028#endif
1029                   iSamplesize = 2;
1030
1031                 break;
1032               }
1033    case  6  : ;                       /* rgb+alpha */
1034    case 14  : {                       /* JPEG rgb+alpha */
1035#ifndef MNG_NO_16BIT_SUPPORT
1036                 if (iBitdepth > 8)
1037                   iSamplesize = 8;
1038                 else
1039#endif
1040                   iSamplesize = 4;
1041
1042                 break;
1043               }
1044  }
1045
1046  iRowsize     = iSamplesize * iWidth;
1047  iImgdatasize = iRowsize    * iHeight;
1048                                       /* buffer size changed ? */
1049  if (iImgdatasize != pBuf->iImgdatasize)
1050  {                                    /* drop the old one */
1051    MNG_FREE (pData, pBuf->pImgdata, pBuf->iImgdatasize);
1052
1053    if (iImgdatasize)                  /* allocate new sample-buffer ? */
1054      MNG_ALLOC (pData, pBuf->pImgdata, iImgdatasize);
1055  }
1056  else
1057  {
1058    if (iImgdatasize)                  /* clear old buffer */
1059    {
1060      mng_uint8p pTemp = pBuf->pImgdata;
1061      mng_uint32 iX;
1062      
1063      for (iX = 0; iX < (iImgdatasize & (mng_uint32)(~3L)); iX += 4)
1064      {
1065        *((mng_uint32p)pTemp) = 0x00000000l;
1066        pTemp += 4;
1067      }
1068
1069      while (pTemp < (pBuf->pImgdata + iImgdatasize))
1070      {
1071        *pTemp = 0;
1072        pTemp++;
1073      }
1074    }
1075  }
1076
1077  pBuf->iSamplesize  = iSamplesize;    /* remember new sizes */
1078  pBuf->iRowsize     = iRowsize;
1079  pBuf->iImgdatasize = iImgdatasize;
1080
1081  if (!pBuf->iPixelsampledepth)        /* set delta sampledepths if empty */
1082    pBuf->iPixelsampledepth = iBitdepth;
1083  if (!pBuf->iAlphasampledepth)
1084    pBuf->iAlphasampledepth = iBitdepth;
1085                                       /* dimension set and clipping not ? */
1086  if ((iWidth) && (iHeight) && (!pImage->bClipped))
1087  {
1088    pImage->iClipl   = 0;              /* set clipping to dimension by default */
1089    pImage->iClipr   = iWidth;
1090    pImage->iClipt   = 0;
1091    pImage->iClipb   = iHeight;
1092  }
1093
1094#ifndef MNG_SKIPCHUNK_MAGN
1095  if (pImage->iId)                     /* reset magnification info ? */
1096  {
1097    pImage->iMAGN_MethodX = 0;
1098    pImage->iMAGN_MethodY = 0;
1099    pImage->iMAGN_MX      = 0;
1100    pImage->iMAGN_MY      = 0;
1101    pImage->iMAGN_ML      = 0;
1102    pImage->iMAGN_MR      = 0;
1103    pImage->iMAGN_MT      = 0;
1104    pImage->iMAGN_MB      = 0;
1105  }
1106#endif
1107
1108  if (bResetall)                       /* reset the other characteristics ? */
1109  {
1110#ifndef MNG_SKIPCHUNK_PAST
1111    pImage->iPastx = 0;
1112    pImage->iPasty = 0;
1113#endif
1114
1115    pBuf->bHasPLTE = MNG_FALSE;
1116    pBuf->bHasTRNS = MNG_FALSE;
1117    pBuf->bHasGAMA = pData->bHasglobalGAMA;
1118#ifndef MNG_SKIPCHUNK_cHRM
1119    pBuf->bHasCHRM = pData->bHasglobalCHRM;
1120#endif
1121    pBuf->bHasSRGB = pData->bHasglobalSRGB;
1122#ifndef MNG_SKIPCHUNK_iCCP
1123    pBuf->bHasICCP = pData->bHasglobalICCP;
1124#endif
1125#ifndef MNG_SKIPCHUNK_bKGD
1126    pBuf->bHasBKGD = pData->bHasglobalBKGD;
1127#endif
1128
1129#ifndef MNG_SKIPCHUNK_iCCP
1130    if (pBuf->iProfilesize)            /* drop possibly old ICC profile */
1131    {
1132      MNG_FREE (pData, pBuf->pProfile, pBuf->iProfilesize);
1133      pBuf->iProfilesize     = 0;
1134    }  
1135#endif
1136
1137    if (pData->bHasglobalGAMA)         /* global gAMA present ? */
1138      pBuf->iGamma           = pData->iGlobalGamma;
1139
1140#ifndef MNG_SKIPCHUNK_cHRM
1141    if (pData->bHasglobalCHRM)         /* global cHRM present ? */
1142    {
1143      pBuf->iWhitepointx     = pData->iGlobalWhitepointx;
1144      pBuf->iWhitepointy     = pData->iGlobalWhitepointy;
1145      pBuf->iPrimaryredx     = pData->iGlobalPrimaryredx;
1146      pBuf->iPrimaryredy     = pData->iGlobalPrimaryredy;
1147      pBuf->iPrimarygreenx   = pData->iGlobalPrimarygreenx;
1148      pBuf->iPrimarygreeny   = pData->iGlobalPrimarygreeny;
1149      pBuf->iPrimarybluex    = pData->iGlobalPrimarybluex;
1150      pBuf->iPrimarybluey    = pData->iGlobalPrimarybluey;
1151    }
1152#endif
1153
1154    if (pData->bHasglobalSRGB)           /* global sRGB present ? */
1155      pBuf->iRenderingintent = pData->iGlobalRendintent;
1156
1157#ifndef MNG_SKIPCHUNK_iCCP
1158    if (pData->bHasglobalICCP)           /* global iCCP present ? */
1159    {
1160      if (pData->iGlobalProfilesize)
1161      {
1162        MNG_ALLOC (pData, pBuf->pProfile, pData->iGlobalProfilesize);
1163        MNG_COPY  (pBuf->pProfile, pData->pGlobalProfile, pData->iGlobalProfilesize);
1164      }
1165
1166      pBuf->iProfilesize     = pData->iGlobalProfilesize;
1167    }
1168#endif
1169
1170#ifndef MNG_SKIPCHUNK_bKGD
1171    if (pData->bHasglobalBKGD)           /* global bKGD present ? */
1172    {
1173      pBuf->iBKGDred         = pData->iGlobalBKGDred;
1174      pBuf->iBKGDgreen       = pData->iGlobalBKGDgreen;
1175      pBuf->iBKGDblue        = pData->iGlobalBKGDblue;
1176    }
1177#endif
1178  }
1179
1180#ifdef MNG_SUPPORT_TRACE
1181  MNG_TRACE (pData, MNG_FN_RESET_OBJECTDETAILS, MNG_LC_END);
1182#endif
1183
1184  return MNG_NOERROR;
1185}
1186
1187/* ************************************************************************** */
1188
1189#if !defined(MNG_NO_DELTA_PNG) || !defined(MNG_SKIPCHUNK_PAST) || !defined(MNG_SKIPCHUNK_MAGN)
1190mng_retcode mng_promote_imageobject (mng_datap  pData,
1191                                     mng_imagep pImage,
1192                                     mng_uint8  iBitdepth,
1193                                     mng_uint8  iColortype,
1194                                     mng_uint8  iFilltype)
1195{
1196  mng_retcode    iRetcode       = MNG_NOERROR;
1197  mng_imagedatap pBuf           = pImage->pImgbuf;
1198  mng_uint32     iW             = pBuf->iWidth;
1199  mng_uint32     iH             = pBuf->iHeight;
1200  mng_uint8p     pNewbuf;
1201  mng_uint32     iNewbufsize;
1202  mng_uint32     iNewrowsize;
1203  mng_uint32     iNewsamplesize = pBuf->iSamplesize;
1204  mng_uint32     iY;
1205  mng_uint8      iTempdepth;
1206
1207#ifdef MNG_SUPPORT_TRACE
1208  MNG_TRACE (pData, MNG_FN_PROMOTE_IMGOBJECT, MNG_LC_START);
1209#endif
1210
1211#ifdef MNG_NO_1_2_4BIT_SUPPORT
1212  if (iBitdepth < 8)
1213    iBitdepth=8;
1214  if (pBuf->iBitdepth < 8)
1215    pBuf->iBitdepth=8;
1216#endif
1217#ifdef MNG_NO_16BIT_SUPPORT
1218  if (iBitdepth > 8)
1219    iBitdepth=8;
1220  if (pBuf->iBitdepth > 8)
1221    pBuf->iBitdepth=8;
1222#endif
1223
1224  pData->fPromoterow    = MNG_NULL;    /* init promotion fields */
1225  pData->fPromBitdepth  = MNG_NULL;
1226  pData->iPromColortype = iColortype;
1227  pData->iPromBitdepth  = iBitdepth;
1228  pData->iPromFilltype  = iFilltype;
1229
1230  if (iBitdepth != pBuf->iBitdepth)    /* determine bitdepth promotion */
1231  {
1232    if (pBuf->iColortype == MNG_COLORTYPE_INDEXED)
1233      iTempdepth = 8;
1234    else
1235      iTempdepth = pBuf->iBitdepth;
1236
1237#ifndef MNG_NO_DELTA_PNG
1238    if (iFilltype == MNG_FILLMETHOD_ZEROFILL)
1239    {
1240      switch (iTempdepth)
1241      {
1242#ifndef MNG_NO_1_2_4BIT_SUPPORT
1243        case 1 : {
1244                   switch (iBitdepth)
1245                   {
1246                     case  2 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_1_2;  break; }
1247                     case  4 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_1_4;  break; }
1248                     case  8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_1_8;  break; }
1249#ifndef MNG_NO_16BIT_SUPPORT
1250                     case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_1_16; break; }
1251#endif
1252                   }
1253                   break;
1254                 }
1255        case 2 : {
1256                   switch (iBitdepth)
1257                   {
1258                     case  4 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_2_4;  break; }
1259                     case  8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_2_8;  break; }
1260#ifndef MNG_NO_16BIT_SUPPORT
1261                     case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_2_16; break; }
1262#endif
1263                   }
1264                   break;
1265                 }
1266        case 4 : {
1267                   switch (iBitdepth)
1268                   {
1269                     case  8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_4_8;  break; }
1270#ifndef MNG_NO_16BIT_SUPPORT
1271                     case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_4_16; break; }
1272#endif
1273                   }
1274                   break;
1275                 }
1276#endif /* MNG_NO_1_2_4BIT_SUPPORT */
1277        case 8 : {
1278#ifndef MNG_NO_16BIT_SUPPORT
1279                   if (iBitdepth == 16)
1280                     pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_8_16;
1281#endif
1282                   break;
1283                 }
1284      }
1285    }
1286    else
1287#endif
1288    {
1289      switch (iTempdepth)
1290      {
1291#ifndef MNG_NO_1_2_4BIT_SUPPORT
1292        case 1 : {
1293                   switch (iBitdepth)
1294                   {
1295                     case  2 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_1_2;  break; }
1296                     case  4 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_1_4;  break; }
1297                     case  8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_1_8;  break; }
1298#ifndef MNG_NO_16BIT_SUPPORT
1299                     case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_1_16; break; }
1300#endif
1301                   }
1302                   break;
1303                 }
1304        case 2 : {
1305                   switch (iBitdepth)
1306                   {
1307                     case  4 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_2_4;  break; }
1308                     case  8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_2_8;  break; }
1309#ifndef MNG_NO_16BIT_SUPPORT
1310                     case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_2_16; break; }
1311#endif
1312                   }
1313                   break;
1314                 }
1315        case 4 : {
1316                   switch (iBitdepth)
1317                   {
1318                     case  8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_4_8;  break; }
1319#ifndef MNG_NO_16BIT_SUPPORT
1320                     case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_4_16; break; }
1321#endif
1322                   }
1323                   break;
1324                 }
1325#endif /* MNG_NO_1_2_4BIT_SUPPORT */
1326        case 8 : {
1327#ifndef MNG_NO_16BIT_SUPPORT
1328                   if (iBitdepth == 16)
1329                     pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_8_16;
1330#endif
1331                   break;
1332                 }
1333      }
1334    }
1335  }
1336                                       /* g -> g */
1337  if ((pBuf->iColortype == MNG_COLORTYPE_GRAY) &&
1338      (iColortype == MNG_COLORTYPE_GRAY))
1339  {
1340    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1341    {
1342#ifndef MNG_NO_16BIT_SUPPORT
1343      if (iBitdepth == 16)
1344        pData->fPromoterow = (mng_fptr)mng_promote_g8_g16;
1345      else
1346#endif
1347        pData->fPromoterow = (mng_fptr)mng_promote_g8_g8;
1348    }
1349
1350    iNewsamplesize = 1;
1351
1352#ifndef MNG_NO_16BIT_SUPPORT
1353    if (iBitdepth == 16)               /* 16-bit wide ? */
1354      iNewsamplesize = 2;
1355#endif
1356  }
1357  else                                 /* g -> ga */
1358  if ((pBuf->iColortype == MNG_COLORTYPE_GRAY) &&
1359      (iColortype == MNG_COLORTYPE_GRAYA))
1360  {
1361    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1362    {
1363#ifndef MNG_NO_16BIT_SUPPORT
1364      if (iBitdepth == 16)
1365        pData->fPromoterow = (mng_fptr)mng_promote_g8_ga16;
1366      else
1367#endif
1368        pData->fPromoterow = (mng_fptr)mng_promote_g8_ga8;
1369    }
1370#ifndef MNG_NO_16BIT_SUPPORT
1371    else                               /* source = 16 bits */
1372      pData->fPromoterow = (mng_fptr)mng_promote_g16_ga16;
1373#endif
1374
1375    iNewsamplesize = 2;
1376
1377#ifndef MNG_NO_16BIT_SUPPORT
1378    if (iBitdepth == 16)               /* 16-bit wide ? */
1379      iNewsamplesize = 4;
1380#endif
1381  }
1382  else                                 /* g -> rgb */
1383  if ((pBuf->iColortype == MNG_COLORTYPE_GRAY) &&
1384      (iColortype == MNG_COLORTYPE_RGB))
1385  {
1386    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1387    {
1388#ifndef MNG_NO_16BIT_SUPPORT
1389      if (iBitdepth == 16)
1390        pData->fPromoterow = (mng_fptr)mng_promote_g8_rgb16;
1391      else
1392#endif
1393        pData->fPromoterow = (mng_fptr)mng_promote_g8_rgb8;
1394    }
1395#ifndef MNG_NO_16BIT_SUPPORT
1396    else                               /* source = 16 bits */
1397      pData->fPromoterow = (mng_fptr)mng_promote_g16_rgb16;
1398#endif
1399
1400    iNewsamplesize = 3;
1401
1402#ifndef MNG_NO_16BIT_SUPPORT
1403    if (iBitdepth == 16)               /* 16-bit wide ? */
1404      iNewsamplesize = 6;
1405#endif
1406  }
1407  else                                 /* g -> rgba */
1408  if ((pBuf->iColortype == MNG_COLORTYPE_GRAY) &&
1409      (iColortype == MNG_COLORTYPE_RGBA))
1410  {
1411    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1412    {
1413#ifndef MNG_NO_16BIT_SUPPORT
1414      if (iBitdepth == 16)
1415        pData->fPromoterow = (mng_fptr)mng_promote_g8_rgba16;
1416      else
1417#endif
1418        pData->fPromoterow = (mng_fptr)mng_promote_g8_rgba8;
1419    }
1420#ifndef MNG_NO_16BIT_SUPPORT
1421    else                               /* source = 16 bits */
1422      pData->fPromoterow = (mng_fptr)mng_promote_g16_rgba16;
1423#endif
1424
1425    iNewsamplesize = 4;
1426
1427#ifndef MNG_NO_16BIT_SUPPORT
1428    if (iBitdepth == 16)               /* 16-bit wide ? */
1429      iNewsamplesize = 8;
1430#endif
1431  }
1432  else                                 /* ga -> ga */
1433  if ((pBuf->iColortype == MNG_COLORTYPE_GRAYA) &&
1434      (iColortype == MNG_COLORTYPE_GRAYA))
1435  {
1436    iNewsamplesize = 2;
1437#ifndef MNG_NO_16BIT_SUPPORT
1438    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1439      if (iBitdepth == 16)
1440        pData->fPromoterow = (mng_fptr)mng_promote_ga8_ga16;
1441    if (iBitdepth == 16)
1442      iNewsamplesize = 4;
1443#endif
1444  }
1445  else                                 /* ga -> rgba */
1446  if ((pBuf->iColortype == MNG_COLORTYPE_GRAYA) &&
1447      (iColortype == MNG_COLORTYPE_RGBA))
1448  {
1449    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1450    {
1451#ifndef MNG_NO_16BIT_SUPPORT
1452      if (iBitdepth == 16)
1453        pData->fPromoterow = (mng_fptr)mng_promote_ga8_rgba16;
1454      else
1455#endif
1456        pData->fPromoterow = (mng_fptr)mng_promote_ga8_rgba8;
1457    }
1458#ifndef MNG_NO_16BIT_SUPPORT
1459    else                               /* source = 16 bits */
1460      pData->fPromoterow = (mng_fptr)mng_promote_ga16_rgba16;
1461#endif
1462
1463    iNewsamplesize = 4;
1464
1465#ifndef MNG_NO_16BIT_SUPPORT
1466    if (iBitdepth == 16)               /* 16-bit wide ? */
1467      iNewsamplesize = 8;
1468#endif
1469  }
1470  else                                 /* rgb -> rgb */
1471  if ((pBuf->iColortype == MNG_COLORTYPE_RGB) &&
1472      (iColortype == MNG_COLORTYPE_RGB))
1473  {
1474    iNewsamplesize = 3;
1475#ifndef MNG_NO_16BIT_SUPPORT
1476    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1477      if (iBitdepth == 16)
1478        pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgb16;
1479    if (iBitdepth == 16)
1480      iNewsamplesize = 6;
1481#endif
1482  }
1483  else                                 /* rgb -> rgba */
1484  if ((pBuf->iColortype == MNG_COLORTYPE_RGB) &&
1485      (iColortype == MNG_COLORTYPE_RGBA))
1486  {
1487    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1488    {
1489#ifndef MNG_NO_16BIT_SUPPORT
1490      if (iBitdepth == 16)
1491        pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgba16;
1492      else
1493#endif
1494        pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgba8;
1495    }
1496#ifndef MNG_NO_16BIT_SUPPORT
1497    else                               /* source = 16 bits */
1498      pData->fPromoterow = (mng_fptr)mng_promote_rgb16_rgba16;
1499#endif
1500
1501    iNewsamplesize = 4;
1502#ifndef MNG_NO_16BIT_SUPPORT
1503    if (iBitdepth == 16)               /* 16-bit wide ? */
1504      iNewsamplesize = 8;
1505#endif
1506  }
1507  else                                 /* indexed -> rgb */
1508  if ((pBuf->iColortype == MNG_COLORTYPE_INDEXED) &&
1509      (iColortype == MNG_COLORTYPE_RGB))
1510  {
1511#ifndef MNG_NO_16BIT_SUPPORT
1512    if (iBitdepth == 16)
1513      pData->fPromoterow = (mng_fptr)mng_promote_idx8_rgb16;
1514    else
1515#endif
1516      pData->fPromoterow = (mng_fptr)mng_promote_idx8_rgb8;
1517
1518    iNewsamplesize = 3;
1519
1520#ifndef MNG_NO_16BIT_SUPPORT
1521    if (iBitdepth == 16)               /* 16-bit wide ? */
1522      iNewsamplesize = 6;
1523#endif
1524  }
1525  else                                 /* indexed -> rgba */
1526  if ((pBuf->iColortype == MNG_COLORTYPE_INDEXED) &&
1527      (iColortype == MNG_COLORTYPE_RGBA))
1528  {
1529#ifndef MNG_NO_16BIT_SUPPORT
1530    if (iBitdepth == 16)
1531      pData->fPromoterow = (mng_fptr)mng_promote_idx8_rgba16;
1532    else
1533#endif
1534      pData->fPromoterow = (mng_fptr)mng_promote_idx8_rgba8;
1535
1536    iNewsamplesize = 4;
1537
1538#ifndef MNG_NO_16BIT_SUPPORT
1539    if (iBitdepth == 16)               /* 16-bit wide ? */
1540      iNewsamplesize = 8;
1541#endif
1542  }
1543  else                                 /* rgba -> rgba */
1544  if ((pBuf->iColortype == MNG_COLORTYPE_RGBA) &&
1545      (iColortype == MNG_COLORTYPE_RGBA))
1546  {
1547    iNewsamplesize = 4;
1548#ifndef MNG_NO_16BIT_SUPPORT
1549    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1550    {
1551      if (iBitdepth == 16)
1552        pData->fPromoterow = (mng_fptr)mng_promote_rgba8_rgba16;
1553    }
1554    if (iBitdepth == 16)               /* 16-bit wide ? */
1555      iNewsamplesize = 8;
1556#endif
1557  }
1558#ifdef MNG_INCLUDE_JNG
1559  else                                 /* JPEG g -> g */
1560  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY) &&
1561      (iColortype == MNG_COLORTYPE_JPEGGRAY))
1562  {
1563    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1564    {
1565#ifndef MNG_NO_16BIT_SUPPORT
1566      if (iBitdepth == 16)
1567        pData->fPromoterow = (mng_fptr)mng_promote_g8_g16;
1568      else
1569#endif
1570        pData->fPromoterow = (mng_fptr)mng_promote_g8_g8;
1571    }
1572
1573    iNewsamplesize = 1;
1574
1575#ifndef MNG_NO_16BIT_SUPPORT
1576    if (iBitdepth == 16)               /* 16-bit wide ? */
1577      iNewsamplesize = 2;
1578#endif
1579  }
1580  else                                 /* JPEG g -> ga */
1581  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY) &&
1582      (iColortype == MNG_COLORTYPE_JPEGGRAYA))
1583  {
1584    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1585    {
1586#ifndef MNG_NO_16BIT_SUPPORT
1587      if (iBitdepth == 16)
1588        pData->fPromoterow = (mng_fptr)mng_promote_g8_ga16;
1589      else
1590#endif
1591        pData->fPromoterow = (mng_fptr)mng_promote_g8_ga8;
1592    }
1593#ifndef MNG_NO_16BIT_SUPPORT
1594    else                               /* source = 16 bits */
1595      pData->fPromoterow = (mng_fptr)mng_promote_g16_ga16;
1596#endif
1597
1598    iNewsamplesize = 2;
1599
1600#ifndef MNG_NO_16BIT_SUPPORT
1601    if (iBitdepth == 16)               /* 16-bit wide ? */
1602      iNewsamplesize = 4;
1603#endif
1604  }
1605  else                                 /* JPEG g -> rgb */
1606  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY) &&
1607      (iColortype == MNG_COLORTYPE_JPEGCOLOR))
1608  {
1609    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1610    {
1611#ifndef MNG_NO_16BIT_SUPPORT
1612      if (iBitdepth == 16)
1613        pData->fPromoterow = (mng_fptr)mng_promote_g8_rgb16;
1614      else
1615#endif
1616        pData->fPromoterow = (mng_fptr)mng_promote_g8_rgb8;
1617    }
1618#ifndef MNG_NO_16BIT_SUPPORT
1619    else                               /* source = 16 bits */
1620      pData->fPromoterow = (mng_fptr)mng_promote_g16_rgb16;
1621#endif
1622
1623    iNewsamplesize = 3;
1624
1625#ifndef MNG_NO_16BIT_SUPPORT
1626    if (iBitdepth == 16)               /* 16-bit wide ? */
1627      iNewsamplesize = 6;
1628#endif
1629  }
1630  else                                 /* JPEG g -> rgba */
1631  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY) &&
1632      (iColortype == MNG_COLORTYPE_JPEGCOLORA))
1633  {
1634    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1635    {
1636#ifndef MNG_NO_16BIT_SUPPORT
1637      if (iBitdepth == 16)
1638        pData->fPromoterow = (mng_fptr)mng_promote_g8_rgba16;
1639      else
1640#endif
1641        pData->fPromoterow = (mng_fptr)mng_promote_g8_rgba8;
1642    }
1643#ifndef MNG_NO_16BIT_SUPPORT
1644    else                               /* source = 16 bits */
1645      pData->fPromoterow = (mng_fptr)mng_promote_g16_rgba16;
1646#endif
1647
1648    iNewsamplesize = 4;
1649
1650#ifndef MNG_NO_16BIT_SUPPORT
1651    if (iBitdepth == 16)               /* 16-bit wide ? */
1652      iNewsamplesize = 8;
1653#endif
1654  }
1655  else                                 /* JPEG ga -> ga */
1656  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAYA) &&
1657      (iColortype == MNG_COLORTYPE_JPEGGRAYA))
1658  {
1659    iNewsamplesize = 2;
1660#ifndef MNG_NO_16BIT_SUPPORT
1661    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1662      if (iBitdepth == 16)
1663        pData->fPromoterow = (mng_fptr)mng_promote_ga8_ga16;
1664    if (iBitdepth == 16)
1665      iNewsamplesize = 4;
1666#endif
1667
1668  }
1669  else                                 /* JPEG ga -> rgba */
1670  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAYA) &&
1671      (iColortype == MNG_COLORTYPE_JPEGCOLORA))
1672  {
1673    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1674    {
1675#ifndef MNG_NO_16BIT_SUPPORT
1676      if (iBitdepth == 16)
1677        pData->fPromoterow = (mng_fptr)mng_promote_ga8_rgba16;
1678      else
1679#endif
1680        pData->fPromoterow = (mng_fptr)mng_promote_ga8_rgba8;
1681    }
1682#ifndef MNG_NO_16BIT_SUPPORT
1683    else                               /* source = 16 bits */
1684      pData->fPromoterow = (mng_fptr)mng_promote_ga16_rgba16;
1685#endif
1686
1687    iNewsamplesize = 4;
1688
1689#ifndef MNG_NO_16BIT_SUPPORT
1690    if (iBitdepth == 16)               /* 16-bit wide ? */
1691      iNewsamplesize = 8;
1692#endif
1693  }
1694  else                                 /* JPEG rgb -> rgb */
1695  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLOR) &&
1696      (iColortype == MNG_COLORTYPE_JPEGCOLOR))
1697  {
1698    iNewsamplesize = 3;
1699#ifndef MNG_NO_16BIT_SUPPORT
1700    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1701      if (iBitdepth == 16)
1702        pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgb16;
1703    if (iBitdepth == 16)
1704      iNewsamplesize = 6;
1705#endif
1706
1707  }
1708  else                                 /* JPEG rgb -> rgba */
1709  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLOR) &&
1710      (iColortype == MNG_COLORTYPE_JPEGCOLORA))
1711  {
1712    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1713    {
1714#ifndef MNG_NO_16BIT_SUPPORT
1715      if (iBitdepth == 16)
1716        pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgba16;
1717      else
1718#endif
1719        pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgba8;
1720    }
1721#ifndef MNG_NO_16BIT_SUPPORT
1722    else                               /* source = 16 bits */
1723      pData->fPromoterow = (mng_fptr)mng_promote_rgb16_rgba16;
1724#endif
1725
1726    iNewsamplesize = 4;
1727
1728#ifndef MNG_NO_16BIT_SUPPORT
1729    if (iBitdepth == 16)               /* 16-bit wide ? */
1730      iNewsamplesize = 8;
1731#endif
1732  }
1733  else                                 /* JPEG rgba -> rgba */
1734  if ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLORA) &&
1735      (iColortype == MNG_COLORTYPE_JPEGCOLORA))
1736  {
1737    iNewsamplesize = 4;
1738#ifndef MNG_NO_16BIT_SUPPORT
1739    if (pBuf->iBitdepth <= 8)          /* source <= 8 bits */
1740      if (iBitdepth == 16)
1741        pData->fPromoterow = (mng_fptr)mng_promote_rgba8_rgba16;
1742    if (iBitdepth == 16)
1743      iNewsamplesize = 8;
1744#endif
1745  }
1746#endif /* JNG */
1747
1748  /* found a proper promotion ? */
1749  if (pData->fPromote