/* * Copyright (c) 2005-2007 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Serialization functions for graphic surfaces. */ #include #include #include "view.h" #include "load_surface.h" const AG_Version agSurfaceVer = { 0, 0 }; enum { RAW_ENCODING, RLE_ENCODING, PNG_ENCODING, JPEG_ENCODING, TIFF_ENCODING }; void AG_WriteSurface(AG_DataSource *ds, AG_Surface *su) { Uint8 *src; int x, y; AG_WriteVersion(ds, "AG_Surface", &agSurfaceVer); AG_WriteUint32(ds, RAW_ENCODING); AG_WriteUint32(ds, su->flags & (AG_SRCCOLORKEY|AG_SRCALPHA|AG_RLEACCEL)); AG_WriteUint16(ds, su->w); AG_WriteUint16(ds, su->h); AG_WriteUint8(ds, su->format->BitsPerPixel); AG_WriteUint8(ds, 0); /* TODO grayscale */ AG_WriteUint32(ds, su->format->Rmask); AG_WriteUint32(ds, su->format->Gmask); AG_WriteUint32(ds, su->format->Bmask); AG_WriteUint32(ds, su->format->Amask); AG_WriteUint8(ds, su->format->alpha); AG_WriteUint32(ds, su->format->colorkey); #if 0 printf("saving %dx%dx%d bpp%s%s surface\n", su->w, su->h, su->format->BitsPerPixel, (su->flags & AG_SRCALPHA) ? " alpha" : "", (su->flags & AG_SRCCOLORKEY) ? " colorkey" : ""); printf("masks: %08x,%08x,%08x,%08x\n", su->format->Rmask, su->format->Gmask, su->format->Bmask, su->format->Amask); printf("colorkey=%08x, alpha=%02x\n", su->format->colorkey, su->format->alpha); #endif if (su->format->BitsPerPixel == 8) { int i; AG_WriteUint32(ds, su->format->palette->ncolors); for (i = 0; i < su->format->palette->ncolors; i++) { AG_WriteUint8(ds, su->format->palette->colors[i].r); AG_WriteUint8(ds, su->format->palette->colors[i].g); AG_WriteUint8(ds, su->format->palette->colors[i].b); } } AG_SurfaceLock(su); src = (Uint8 *)su->pixels; for (y = 0; y < su->h; y++) { for (x = 0; x < su->w; x++) { switch (su->format->BytesPerPixel) { case 4: AG_WriteUint32(ds, *(Uint32 *)src); break; case 3: #if AG_BYTEORDER == AG_BIG_ENDIAN AG_WriteUint32(ds, (src[0] << 16) + (src[1] << 8) + src[2]); #else AG_WriteUint32(ds, (src[2] << 16) + (src[1] << 8) + src[0]); #endif break; case 2: AG_WriteUint16(ds, *(Uint16 *)src); break; case 1: /* XXX do one big write */ AG_WriteUint8(ds, *src); break; } src += su->format->BytesPerPixel; } } AG_SurfaceUnlock(su); } AG_Surface * AG_ReadSurface(AG_DataSource *ds, AG_PixelFormat *pixfmt) { AG_Surface *su; Uint32 encoding; Uint32 flags; Uint16 w, h; Uint8 depth, grayscale; Uint32 Rmask, Gmask, Bmask, Amask; Uint8 *dst; int x, y; if (AG_ReadVersion(ds, "AG_Surface", &agSurfaceVer, NULL) != 0) return (NULL); encoding = AG_ReadUint32(ds); if (encoding != RAW_ENCODING) { AG_SetError(_("Unsupported surface encoding: %u"), (unsigned int)encoding); return (NULL); } flags = AG_ReadUint32(ds); w = AG_ReadUint16(ds); h = AG_ReadUint16(ds); depth = AG_ReadUint8(ds); grayscale = AG_ReadUint8(ds); Rmask = AG_ReadUint32(ds); Gmask = AG_ReadUint32(ds); Bmask = AG_ReadUint32(ds); Amask = AG_ReadUint32(ds); su = AG_SurfaceRGBA(w, h, depth, flags, Rmask,Gmask,Bmask,Amask); su->format->alpha = AG_ReadUint8(ds); su->format->colorkey = AG_ReadUint32(ds); #if 0 printf("loading %dx%dx%d bpp%s%s%s surface\n", w, h, depth, grayscale ? " grayscale" : "", (flags & AG_SRCALPHA) ? " alpha" : "", (flags & AG_SRCCOLORKEY) ? " colorkey" : ""); printf("masks: %08x,%08x,%08x,%08x\n", Rmask, Gmask, Bmask, Amask); printf("colorkey=%08x, alpha=%02x\n", su->format->colorkey, su->format->alpha); #endif if (depth == 8) { AG_Color *colors; Uint32 i, ncolors; ncolors = AG_ReadUint32(ds); colors = Malloc(ncolors*sizeof(AG_Color)); if (grayscale) { for (i = 0; i < ncolors; i++) { colors[i].r = i; colors[i].g = i; colors[i].b = i; } } else { for (i = 0; i < ncolors; i++) { colors[i].r = AG_ReadUint8(ds); colors[i].g = AG_ReadUint8(ds); colors[i].b = AG_ReadUint8(ds); } } AG_SetPalette(su, AG_LOGPAL|AG_PHYSPAL, colors, 0, ncolors); Free(colors); } AG_SurfaceLock(su); dst = (Uint8 *)su->pixels; for (y = 0; y < su->h; y++) { for (x = 0; x < su->w; x++) { switch (su->format->BytesPerPixel) { case 4: *(Uint32 *)dst = AG_ReadUint32(ds); break; case 3: { Uint32 c = AG_ReadUint32(ds); #if AG_BYTEORDER == AG_BIG_ENDIAN dst[0] = (c >> 16) & 0xff; dst[1] = (c >> 8) & 0xff; dst[2] = c & 0xff; #else dst[2] = (c >> 16) & 0xff; dst[1] = (c >> 8) & 0xff; dst[0] = c & 0xff; #endif } break; case 2: *(Uint16 *)dst = AG_ReadUint16(ds); break; case 1: /* XXX do one big read */ *dst = AG_ReadUint8(ds); break; } dst += su->format->BytesPerPixel; } } AG_SurfaceUnlock(su); return (su); }