Advertisement
Danicron

effthat

Aug 14th, 2019
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.79 KB | None | 0 0
  1. /*
  2.  *  c16Image.cpp
  3.  *  openc2e
  4.  *
  5.  *  Created by Alyssa Milburn on Sat May 22 2004.
  6.  *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
  7.  *
  8.  *  This library is free software; you can redistribute it and/or
  9.  *  modify it under the terms of the GNU Lesser General Public
  10.  *  License as published by the Free Software Foundation; either
  11.  *  version 2 of the License, or (at your option) any later version.
  12.  *
  13.  *  This library is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  *  Lesser General Public License for more details.
  17.  *
  18.  */
  19.  
  20. #include "c16Image.h"
  21. #include "openc2e.h"
  22.  
  23. void c16Image::readHeader(std::istream &in) {
  24.     uint32 flags; uint16 spritecount;
  25.     in.read((char *)&flags, 4); flags = swapEndianLong(flags);
  26.     is_565 = (flags & 0x01);
  27.     assert(flags & 0x02);
  28.     in.read((char *)&spritecount, 2); m_numframes = swapEndianShort(spritecount);
  29.  
  30.     widths = new unsigned short[m_numframes];
  31.     heights = new unsigned short[m_numframes];
  32.     lineoffsets = new unsigned int *[m_numframes];
  33.  
  34.     // first, read the headers.
  35.     for (unsigned int i = 0; i < m_numframes; i++) {
  36.         uint32 offset;
  37.         in.read((char *)&offset, 4); offset = swapEndianLong(offset);
  38.         in.read((char *)&widths[i], 2); widths[i] = swapEndianShort(widths[i]);
  39.         in.read((char *)&heights[i], 2); heights[i] = swapEndianShort(heights[i]);
  40.         lineoffsets[i] = new unsigned int[heights[i]];
  41.         lineoffsets[i][0] = offset;
  42.         for (unsigned int j = 1; j < heights[i]; j++) {
  43.             in.read((char *)&lineoffsets[i][j], 4); lineoffsets[i][j] = swapEndianLong(lineoffsets[i][j]);
  44.         }
  45.     }
  46. }
  47.  
  48. shared_ptr<creaturesImage> c16Image::mutableCopy() {
  49.     s16Image *img = new s16Image();
  50.  
  51.     img->imgformat = if_16bit;
  52.     img->is_565 = is_565;
  53.     img->m_numframes = m_numframes;
  54.     img->offsets = 0;
  55.     img->widths = new unsigned short[m_numframes];
  56.     memcpy(img->widths, widths, m_numframes * sizeof(unsigned short));
  57.     img->heights = new unsigned short[m_numframes];
  58.     memcpy(img->heights, heights, m_numframes * sizeof(unsigned short));
  59.     img->buffers = new void *[m_numframes];
  60.     for (unsigned int i = 0; i < m_numframes; i++) {
  61.         img->buffers[i] = new char[widths[i] * heights[i] * 2];
  62.         memcpy(img->buffers[i], buffers[i], widths[i] * heights[i] * 2);
  63.     }
  64.  
  65.     return shared_ptr<creaturesImage>(img);
  66. }
  67.  
  68. shared_ptr<creaturesImage> s16Image::mutableCopy() {
  69.     s16Image *img = new s16Image();
  70.  
  71.     img->imgformat = if_16bit;
  72.     img->is_565 = is_565;
  73.     img->m_numframes = m_numframes;
  74.     img->offsets = 0;
  75.     img->widths = new unsigned short[m_numframes];
  76.     memcpy(img->widths, widths, m_numframes * sizeof(unsigned short));
  77.     img->heights = new unsigned short[m_numframes];
  78.     memcpy(img->heights, heights, m_numframes * sizeof(unsigned short));
  79.     img->buffers = new void *[m_numframes];
  80.     for (unsigned int i = 0; i < m_numframes; i++) {
  81.         img->buffers[i] = new char[widths[i] * heights[i] * 2];
  82.         memcpy(img->buffers[i], buffers[i], widths[i] * heights[i] * 2);
  83.     }
  84.    
  85.     return shared_ptr<creaturesImage>(img);
  86. }
  87.  
  88. c16Image::c16Image(mmapifstream *in, std::string n) : creaturesImage(n) {
  89.     stream = in;
  90.     imgformat = if_16bit;
  91.  
  92.     readHeader(*in);
  93.    
  94.     buffers = new void *[m_numframes];
  95.    
  96.     // then, read the files. this involves seeking around, and is hence immensely ghey
  97.     // todo: we assume the file format is valid here. we shouldn't.
  98.     for (unsigned int i = 0; i < m_numframes; i++) {
  99.         buffers[i] = new char[widths[i] * heights[i] * 2];
  100.         uint16 *bufferpos = (uint16 *)buffers[i];
  101.         for (unsigned int j = 0; j < heights[i]; j++) {
  102.             in->seekg(lineoffsets[i][j], std::ios::beg);
  103.             while (true) {
  104.                 uint16 tag; in->read((char *)&tag, 2); tag = swapEndianShort(tag);
  105.                 if (tag == 0) break;
  106.                 bool transparentrun = ((tag & 0x0001) == 0);
  107.                 uint16 runlength = (tag & 0xFFFE) >> 1;
  108.                 if (transparentrun)
  109.                     memset((char *)bufferpos, 0, (runlength * 2));
  110.                 else {
  111.                     in->read((char *)bufferpos, (runlength * 2));
  112.                     for (unsigned int k = 0; k < runlength; k++) {
  113.                         bufferpos[k] = swapEndianShort(bufferpos[k]);
  114.                     }
  115.                 }
  116.                 bufferpos += runlength;
  117.             }
  118.         }
  119.         delete[] lineoffsets[i];
  120.     }
  121.     delete[] lineoffsets;
  122. }
  123.  
  124. void s16Image::readHeader(std::istream &in) {
  125.     uint32 flags; uint16 spritecount;
  126.     in.read((char *)&flags, 4); flags = swapEndianLong(flags);
  127.     is_565 = (flags & 0x01);
  128.     in.read((char *)&spritecount, 2); m_numframes = swapEndianShort(spritecount);
  129.    
  130.     widths = new unsigned short[m_numframes];
  131.     heights = new unsigned short[m_numframes];
  132.     offsets = new unsigned int[m_numframes];
  133.  
  134.     // first, read the headers.
  135.     for (unsigned int i = 0; i < m_numframes; i++) {
  136.         in.read((char *)&offsets[i], 4); offsets[i] = swapEndianLong(offsets[i]);
  137.         in.read((char *)&widths[i], 2); widths[i] = swapEndianShort(widths[i]);
  138.         in.read((char *)&heights[i], 2); heights[i] = swapEndianShort(heights[i]);
  139.     }
  140. }
  141.  
  142. void s16Image::writeHeader(std::ostream &s) {
  143.     unsigned int dw; unsigned short w;
  144.    
  145.     dw = (is_565 ? 1 : 0);
  146.     dw = swapEndianLong(dw); s.write((char *)&dw, 4);
  147.     w = m_numframes;
  148.     w = swapEndianShort(w); s.write((char *)&w, 2);
  149.    
  150.     for (unsigned int i = 0; i < m_numframes; i++) {
  151.         dw = offsets[i];
  152.         dw = swapEndianLong(dw); s.write((char *)&dw, 4);
  153.         w = widths[i];
  154.         w = swapEndianShort(w); s.write((char *)&w, 2);
  155.         w = heights[i];
  156.         w = swapEndianShort(w); s.write((char *)&w, 2);
  157.     }
  158. }
  159.  
  160. bool s16Image::transparentAt(unsigned int frame, unsigned int x, unsigned int y) {
  161.     unsigned int offset = (y * widths[frame]) + x;
  162.     unsigned short *buffer = (unsigned short *)buffers[frame];
  163.     return (buffer[offset] == 0);
  164. }
  165.  
  166. bool c16Image::transparentAt(unsigned int frame, unsigned int x, unsigned int y) {
  167.     unsigned int offset = (y * widths[frame]) + x;
  168.     unsigned short *buffer = (unsigned short *)buffers[frame];
  169.     return (buffer[offset] == 0);
  170. }
  171.  
  172. s16Image::s16Image(mmapifstream *in, std::string n) : creaturesImage(n) {
  173.     stream = in;
  174.     imgformat = if_16bit;
  175.  
  176.     readHeader(*in);
  177.    
  178.     buffers = new void *[m_numframes];
  179.  
  180.     for (unsigned int i = 0; i < m_numframes; i++)
  181.         buffers[i] = in->map + offsets[i];
  182.  
  183.     delete[] offsets;
  184. }
  185.  
  186. s16Image::~s16Image() {
  187.     delete[] widths;
  188.     delete[] heights;
  189.     if (!stream) { // make sure this isn't a damn mmapifstream..
  190.         for (unsigned int i = 0; i < m_numframes; i++)
  191.             delete[] (uint16 *)buffers[i];
  192.     }
  193.     delete[] buffers;
  194.     // TODO: we should never have 'offsets' left over here, but .. we should check
  195. }
  196.  
  197. c16Image::~c16Image() {
  198.     delete[] widths;
  199.     delete[] heights;
  200.     for (unsigned int i = 0; i < m_numframes; i++)
  201.         delete[] (uint16 *)buffers[i];
  202.     delete[] buffers;
  203.     // TODO: we should never have 'offsets' left over here, but .. we should check
  204. }
  205.  
  206. void s16Image::tint(unsigned char r, unsigned char g, unsigned char b, unsigned char rotation, unsigned char swap) {
  207.     assert(!stream); // this only works on duplicated images
  208.  
  209.     if (128 == r && 128 == g && 128  == b && 128  == rotation && 128 == swap) return; // duh
  210.  
  211.     /*
  212.      * CDN:
  213.      * if rotation >= 128
  214.      * absRot = rotation-128
  215.      * else
  216.      * absRot = 128 - rotation
  217.      * endif
  218.      * invRot = 127-absRot
  219.      */
  220.     int absRot;
  221.     if (rotation >= 128)
  222.         absRot = (int)rotation - 128;
  223.     else
  224.         absRot = 128 - (int)rotation;
  225.     int invRot = 127 - absRot;
  226.  
  227.     /*
  228.      * CDN:
  229.      * if swap >= 128
  230.      * absSwap = swap - 128
  231.      * else
  232.      * absSwap = 128 - swap
  233.      * endif
  234.      * invSwap = 127-absSwap
  235.      */
  236.     int absSwap;
  237.     if (swap >= 128)
  238.         absSwap = (int)swap - 128;
  239.     else
  240.         absSwap = 128 - (int)swap;
  241.     int invSwap = 127 - absSwap;
  242.    
  243.     /*
  244.      * CDN:
  245.      * redTint = red-128
  246.      * greenTint = green-128
  247.      * blueTint = blue-128
  248.      */
  249.  
  250.     int redTint = (int)r - 128;
  251.     int greenTint = (int)g - 128;
  252.     int blueTint = (int)b - 128;
  253.  
  254.     for (unsigned int i = 0; i < m_numframes; i++) {
  255.         for (unsigned int j = 0; j < heights[i]; j++) {
  256.             for (unsigned int k = 0; k < widths[i]; k++) {
  257.                 unsigned short v = ((unsigned short *)buffers[i])[(j * widths[i]) + k];
  258.                 if (v == 0) continue;
  259.  
  260.                 /*
  261.                  * CDN:
  262.                  * tempRed = RedValue + redTint;
  263.                  * tempGreen = GreenValue + greenTint;
  264.                  * tempBlue = BlueValue + blueTint;
  265.                  */
  266.                 int red = (((uint32)(v) & 0xf800) >> 8) + redTint;
  267.                 if (red < 0) red = 0; else if (red > 255) red = 255;
  268.                 int green = (((uint32)(v) & 0x07e0) >> 3) + greenTint;
  269.                 if (green < 0) green = 0; else if (green > 255) green = 255;
  270.                 int blue = (((uint32)(v) & 0x001f) << 3) + blueTint;
  271.                 if (blue < 0) blue = 0; else if (blue > 255) blue = 255;
  272.  
  273.                 /*
  274.                  * CDN:
  275.                  * if (rotation < 128)
  276.                  * rotRed = ((absRot * tempBlue) + (invRot * tempRed)) / 256
  277.                  * rotGreen = ((absRot * tempRed) + (invRot * tempGreen)) / 256
  278.                  * rotBlue = ((absRot * tempGreen) + (invRot * tempBlue)) / 256
  279.                  * endif
  280.                  */
  281.  
  282.                 int rotRed, rotGreen, rotBlue;
  283.                 rotRed = ((blue * absRot) + (red * invRot)) / 128;
  284.                 rotGreen = ((red * absRot) + (green * invRot)) / 128;
  285.                 rotBlue = ((green * absRot) + (blue * invRot)) / 128;
  286.  
  287.  
  288.                 /*
  289.                  * CDN:
  290.                  * swappedRed = ((absSwap * rotBlue) + (invSwap * rotRed))/256
  291.                  * swappedBlue = ((absSwap * rotRed) + (invSwap * rotBlue))/256
  292.                  *
  293.                  * fuzzie notes that this doesn't seem to be a no-op for swap=128..
  294.                  */
  295.                 int swappedRed = ((absSwap * blue) + (invSwap * red)) / 128;
  296.                 int swappedBlue = ((absSwap * red) + (invSwap * blue)) / 128;
  297.  
  298.                 /*
  299.                  * SetColour(definedcolour to (swappedRed,rotGreen,swappedBlue))
  300.                  */
  301.                 swappedRed = (swappedRed << 8) & 0xf800;
  302.                 rotGreen = (rotGreen << 3) & 0x7e0;
  303.                 swappedBlue = (swappedBlue >> 3) & 0x1f;
  304.                 v = (swappedRed | rotGreen | swappedBlue);
  305.                 /*
  306.                  * if definedcolour ==0 SetColour(definedcolour to (1,1,1))
  307.                  */
  308.                 if (v == 0)
  309.                     v = (1 << 11 | 1 << 5 | 1);
  310.                 ((unsigned short *)buffers[i])[(j * widths[i]) + k] = v;
  311.             }
  312.         }
  313.     }
  314. }
  315.  
  316. /* vim: set noet: */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement