src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c
changeset 47216 71c04702a3d5
parent 40701 cfe188d1a054
child 54407 901ff5aba330
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     3  *
       
     4  * This code is free software; you can redistribute it and/or modify it
       
     5  * under the terms of the GNU General Public License version 2 only, as
       
     6  * published by the Free Software Foundation.  Oracle designates this
       
     7  * particular file as subject to the "Classpath" exception as provided
       
     8  * by Oracle in the LICENSE file that accompanied this code.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21  * or visit www.oracle.com if you need additional information or have any
       
    22  * questions.
       
    23  */
       
    24 
       
    25 /*****************************************************************************
       
    26 
       
    27  GIF construction tools
       
    28 
       
    29 ****************************************************************************/
       
    30 
       
    31 #include <stdlib.h>
       
    32 #include <stdio.h>
       
    33 #include <string.h>
       
    34 
       
    35 #include "gif_lib.h"
       
    36 
       
    37 #define MAX(x, y)    (((x) > (y)) ? (x) : (y))
       
    38 
       
    39 /******************************************************************************
       
    40  Miscellaneous utility functions
       
    41 ******************************************************************************/
       
    42 
       
    43 /* return smallest bitfield size n will fit in */
       
    44 int
       
    45 GifBitSize(int n)
       
    46 {
       
    47     register int i;
       
    48 
       
    49     for (i = 1; i <= 8; i++)
       
    50         if ((1 << i) >= n)
       
    51             break;
       
    52     return (i);
       
    53 }
       
    54 
       
    55 /******************************************************************************
       
    56   Color map object functions
       
    57 ******************************************************************************/
       
    58 
       
    59 /*
       
    60  * Allocate a color map of given size; initialize with contents of
       
    61  * ColorMap if that pointer is non-NULL.
       
    62  */
       
    63 ColorMapObject *
       
    64 GifMakeMapObject(int ColorCount, const GifColorType *ColorMap)
       
    65 {
       
    66     ColorMapObject *Object;
       
    67 
       
    68     /*** FIXME: Our ColorCount has to be a power of two.  Is it necessary to
       
    69      * make the user know that or should we automatically round up instead? */
       
    70     if (ColorCount != (1 << GifBitSize(ColorCount))) {
       
    71         return ((ColorMapObject *) NULL);
       
    72     }
       
    73 
       
    74     Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
       
    75     if (Object == (ColorMapObject *) NULL) {
       
    76         return ((ColorMapObject *) NULL);
       
    77     }
       
    78 
       
    79     Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
       
    80     if (Object->Colors == (GifColorType *) NULL) {
       
    81         free(Object);
       
    82         return ((ColorMapObject *) NULL);
       
    83     }
       
    84 
       
    85     Object->ColorCount = ColorCount;
       
    86     Object->BitsPerPixel = GifBitSize(ColorCount);
       
    87     Object->SortFlag = false;
       
    88 
       
    89     if (ColorMap != NULL) {
       
    90         memcpy((char *)Object->Colors,
       
    91                (char *)ColorMap, ColorCount * sizeof(GifColorType));
       
    92     }
       
    93 
       
    94     return (Object);
       
    95 }
       
    96 
       
    97 /*******************************************************************************
       
    98 Free a color map object
       
    99 *******************************************************************************/
       
   100 void
       
   101 GifFreeMapObject(ColorMapObject *Object)
       
   102 {
       
   103     if (Object != NULL) {
       
   104         (void)free(Object->Colors);
       
   105         (void)free(Object);
       
   106     }
       
   107 }
       
   108 
       
   109 #ifdef DEBUG
       
   110 void
       
   111 DumpColorMap(ColorMapObject *Object,
       
   112              FILE * fp)
       
   113 {
       
   114     if (Object != NULL) {
       
   115         int i, j, Len = Object->ColorCount;
       
   116 
       
   117         for (i = 0; i < Len; i += 4) {
       
   118             for (j = 0; j < 4 && j < Len; j++) {
       
   119                 (void)fprintf(fp, "%3d: %02x %02x %02x   ", i + j,
       
   120                               Object->Colors[i + j].Red,
       
   121                               Object->Colors[i + j].Green,
       
   122                               Object->Colors[i + j].Blue);
       
   123             }
       
   124             (void)fprintf(fp, "\n");
       
   125         }
       
   126     }
       
   127 }
       
   128 #endif /* DEBUG */
       
   129 
       
   130 /*******************************************************************************
       
   131  Compute the union of two given color maps and return it.  If result can't
       
   132  fit into 256 colors, NULL is returned, the allocated union otherwise.
       
   133  ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
       
   134  copied iff they didn't exist before.  ColorTransIn2 maps the old
       
   135  ColorIn2 into the ColorUnion color map table./
       
   136 *******************************************************************************/
       
   137 ColorMapObject *
       
   138 GifUnionColorMap(const ColorMapObject *ColorIn1,
       
   139               const ColorMapObject *ColorIn2,
       
   140               GifPixelType ColorTransIn2[])
       
   141 {
       
   142     int i, j, CrntSlot, RoundUpTo, NewGifBitSize;
       
   143     ColorMapObject *ColorUnion;
       
   144 
       
   145     /*
       
   146      * We don't worry about duplicates within either color map; if
       
   147      * the caller wants to resolve those, he can perform unions
       
   148      * with an empty color map.
       
   149      */
       
   150 
       
   151     /* Allocate table which will hold the result for sure. */
       
   152     ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount,
       
   153                                ColorIn2->ColorCount) * 2, NULL);
       
   154 
       
   155     if (ColorUnion == NULL)
       
   156         return (NULL);
       
   157 
       
   158     /*
       
   159      * Copy ColorIn1 to ColorUnion.
       
   160      */
       
   161     for (i = 0; i < ColorIn1->ColorCount; i++)
       
   162         ColorUnion->Colors[i] = ColorIn1->Colors[i];
       
   163     CrntSlot = ColorIn1->ColorCount;
       
   164 
       
   165     /*
       
   166      * Potentially obnoxious hack:
       
   167      *
       
   168      * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
       
   169      * of table 1.  This is very useful if your display is limited to
       
   170      * 16 colors.
       
   171      */
       
   172     while (ColorIn1->Colors[CrntSlot - 1].Red == 0
       
   173            && ColorIn1->Colors[CrntSlot - 1].Green == 0
       
   174            && ColorIn1->Colors[CrntSlot - 1].Blue == 0)
       
   175         CrntSlot--;
       
   176 
       
   177     /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */
       
   178     for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
       
   179         /* Let's see if this color already exists: */
       
   180         for (j = 0; j < ColorIn1->ColorCount; j++)
       
   181             if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i],
       
   182                         sizeof(GifColorType)) == 0)
       
   183                 break;
       
   184 
       
   185         if (j < ColorIn1->ColorCount)
       
   186             ColorTransIn2[i] = j;    /* color exists in Color1 */
       
   187         else {
       
   188             /* Color is new - copy it to a new slot: */
       
   189             ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
       
   190             ColorTransIn2[i] = CrntSlot++;
       
   191         }
       
   192     }
       
   193 
       
   194     if (CrntSlot > 256) {
       
   195         GifFreeMapObject(ColorUnion);
       
   196         return ((ColorMapObject *) NULL);
       
   197     }
       
   198 
       
   199     NewGifBitSize = GifBitSize(CrntSlot);
       
   200     RoundUpTo = (1 << NewGifBitSize);
       
   201 
       
   202     if (RoundUpTo != ColorUnion->ColorCount) {
       
   203         register GifColorType *Map = ColorUnion->Colors;
       
   204 
       
   205         /*
       
   206          * Zero out slots up to next power of 2.
       
   207          * We know these slots exist because of the way ColorUnion's
       
   208          * start dimension was computed.
       
   209          */
       
   210         for (j = CrntSlot; j < RoundUpTo; j++)
       
   211             Map[j].Red = Map[j].Green = Map[j].Blue = 0;
       
   212 
       
   213         /* perhaps we can shrink the map? */
       
   214         if (RoundUpTo < ColorUnion->ColorCount) {
       
   215             GifColorType *new_map = (GifColorType *)reallocarray(Map,
       
   216                                  RoundUpTo, sizeof(GifColorType));
       
   217             if( new_map == NULL ) {
       
   218                 GifFreeMapObject(ColorUnion);
       
   219                 return ((ColorMapObject *) NULL);
       
   220             }
       
   221             ColorUnion->Colors = new_map;
       
   222         }
       
   223     }
       
   224 
       
   225     ColorUnion->ColorCount = RoundUpTo;
       
   226     ColorUnion->BitsPerPixel = NewGifBitSize;
       
   227 
       
   228     return (ColorUnion);
       
   229 }
       
   230 
       
   231 /*******************************************************************************
       
   232  Apply a given color translation to the raster bits of an image
       
   233 *******************************************************************************/
       
   234 void
       
   235 GifApplyTranslation(SavedImage *Image, GifPixelType Translation[])
       
   236 {
       
   237     register int i;
       
   238     register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
       
   239 
       
   240     for (i = 0; i < RasterSize; i++)
       
   241         Image->RasterBits[i] = Translation[Image->RasterBits[i]];
       
   242 }
       
   243 
       
   244 /******************************************************************************
       
   245  Extension record functions
       
   246 ******************************************************************************/
       
   247 int
       
   248 GifAddExtensionBlock(int *ExtensionBlockCount,
       
   249                      ExtensionBlock **ExtensionBlocks,
       
   250                      int Function,
       
   251                      unsigned int Len,
       
   252                      unsigned char ExtData[])
       
   253 {
       
   254     ExtensionBlock *ep;
       
   255 
       
   256     if (*ExtensionBlocks == NULL)
       
   257         *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
       
   258     else {
       
   259         ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray
       
   260                                       (*ExtensionBlocks, (*ExtensionBlockCount + 1),
       
   261                                       sizeof(ExtensionBlock));
       
   262         if( ep_new == NULL )
       
   263             return (GIF_ERROR);
       
   264         *ExtensionBlocks = ep_new;
       
   265     }
       
   266 
       
   267     if (*ExtensionBlocks == NULL)
       
   268         return (GIF_ERROR);
       
   269 
       
   270     ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++];
       
   271 
       
   272     ep->Function = Function;
       
   273     ep->ByteCount=Len;
       
   274     ep->Bytes = (GifByteType *)malloc(ep->ByteCount);
       
   275     if (ep->Bytes == NULL)
       
   276         return (GIF_ERROR);
       
   277 
       
   278     if (ExtData != NULL) {
       
   279         memcpy(ep->Bytes, ExtData, Len);
       
   280     }
       
   281 
       
   282     return (GIF_OK);
       
   283 }
       
   284 
       
   285 void
       
   286 GifFreeExtensions(int *ExtensionBlockCount,
       
   287                   ExtensionBlock **ExtensionBlocks)
       
   288 {
       
   289     ExtensionBlock *ep;
       
   290 
       
   291     if (*ExtensionBlocks == NULL)
       
   292         return;
       
   293 
       
   294     for (ep = *ExtensionBlocks;
       
   295          ep < (*ExtensionBlocks + *ExtensionBlockCount);
       
   296          ep++)
       
   297         (void)free((char *)ep->Bytes);
       
   298     (void)free((char *)*ExtensionBlocks);
       
   299     *ExtensionBlocks = NULL;
       
   300     *ExtensionBlockCount = 0;
       
   301 }
       
   302 
       
   303 /******************************************************************************
       
   304  Image block allocation functions
       
   305 ******************************************************************************/
       
   306 
       
   307 /* Private Function:
       
   308  * Frees the last image in the GifFile->SavedImages array
       
   309  */
       
   310 void
       
   311 FreeLastSavedImage(GifFileType *GifFile)
       
   312 {
       
   313     SavedImage *sp;
       
   314 
       
   315     if ((GifFile == NULL) || (GifFile->SavedImages == NULL))
       
   316         return;
       
   317 
       
   318     /* Remove one SavedImage from the GifFile */
       
   319     GifFile->ImageCount--;
       
   320     sp = &GifFile->SavedImages[GifFile->ImageCount];
       
   321 
       
   322     /* Deallocate its Colormap */
       
   323     if (sp->ImageDesc.ColorMap != NULL) {
       
   324         GifFreeMapObject(sp->ImageDesc.ColorMap);
       
   325         sp->ImageDesc.ColorMap = NULL;
       
   326     }
       
   327 
       
   328     /* Deallocate the image data */
       
   329     if (sp->RasterBits != NULL)
       
   330         free((char *)sp->RasterBits);
       
   331 
       
   332     /* Deallocate any extensions */
       
   333     GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
       
   334 
       
   335     /*** FIXME: We could realloc the GifFile->SavedImages structure but is
       
   336      * there a point to it? Saves some memory but we'd have to do it every
       
   337      * time.  If this is used in GifFreeSavedImages then it would be inefficient
       
   338      * (The whole array is going to be deallocated.)  If we just use it when
       
   339      * we want to free the last Image it's convenient to do it here.
       
   340      */
       
   341 }
       
   342 
       
   343 /*
       
   344  * Append an image block to the SavedImages array
       
   345  */
       
   346 SavedImage *
       
   347 GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
       
   348 {
       
   349     if (GifFile->SavedImages == NULL)
       
   350         GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
       
   351     else
       
   352         GifFile->SavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,
       
   353                                (GifFile->ImageCount + 1), sizeof(SavedImage));
       
   354 
       
   355     if (GifFile->SavedImages == NULL)
       
   356         return ((SavedImage *)NULL);
       
   357     else {
       
   358         SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++];
       
   359         memset((char *)sp, '\0', sizeof(SavedImage));
       
   360 
       
   361         if (CopyFrom != NULL) {
       
   362             memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
       
   363 
       
   364             /*
       
   365              * Make our own allocated copies of the heap fields in the
       
   366              * copied record.  This guards against potential aliasing
       
   367              * problems.
       
   368              */
       
   369 
       
   370             /* first, the local color map */
       
   371             if (sp->ImageDesc.ColorMap != NULL) {
       
   372                 sp->ImageDesc.ColorMap = GifMakeMapObject(
       
   373                                          CopyFrom->ImageDesc.ColorMap->ColorCount,
       
   374                                          CopyFrom->ImageDesc.ColorMap->Colors);
       
   375                 if (sp->ImageDesc.ColorMap == NULL) {
       
   376                     FreeLastSavedImage(GifFile);
       
   377                     return (SavedImage *)(NULL);
       
   378                 }
       
   379             }
       
   380 
       
   381             /* next, the raster */
       
   382             sp->RasterBits = (unsigned char *)reallocarray(NULL,
       
   383                                                   (CopyFrom->ImageDesc.Height *
       
   384                                                   CopyFrom->ImageDesc.Width),
       
   385                                                   sizeof(GifPixelType));
       
   386             if (sp->RasterBits == NULL) {
       
   387                 FreeLastSavedImage(GifFile);
       
   388                 return (SavedImage *)(NULL);
       
   389             }
       
   390             memcpy(sp->RasterBits, CopyFrom->RasterBits,
       
   391                    sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *
       
   392                    CopyFrom->ImageDesc.Width);
       
   393 
       
   394             /* finally, the extension blocks */
       
   395             if (sp->ExtensionBlocks != NULL) {
       
   396                 sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL,
       
   397                                       CopyFrom->ExtensionBlockCount,
       
   398                                       sizeof(ExtensionBlock));
       
   399                 if (sp->ExtensionBlocks == NULL) {
       
   400                     FreeLastSavedImage(GifFile);
       
   401                     return (SavedImage *)(NULL);
       
   402                 }
       
   403                 memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,
       
   404                        sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
       
   405             }
       
   406         }
       
   407 
       
   408         return (sp);
       
   409     }
       
   410 }
       
   411 
       
   412 void
       
   413 GifFreeSavedImages(GifFileType *GifFile)
       
   414 {
       
   415     SavedImage *sp;
       
   416 
       
   417     if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
       
   418         return;
       
   419     }
       
   420     for (sp = GifFile->SavedImages;
       
   421          sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
       
   422         if (sp->ImageDesc.ColorMap != NULL) {
       
   423             GifFreeMapObject(sp->ImageDesc.ColorMap);
       
   424             sp->ImageDesc.ColorMap = NULL;
       
   425         }
       
   426 
       
   427         if (sp->RasterBits != NULL)
       
   428             free((char *)sp->RasterBits);
       
   429 
       
   430         GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
       
   431     }
       
   432     free((char *)GifFile->SavedImages);
       
   433     GifFile->SavedImages = NULL;
       
   434 }
       
   435 
       
   436 /* end */