1 /*
2     Copyright (c) 2005-2021 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 /*
18     The original source for this example is
19     Copyright (c) 1994-2008 John E. Stone
20     All rights reserved.
21 
22     Redistribution and use in source and binary forms, with or without
23     modification, are permitted provided that the following conditions
24     are met:
25     1. Redistributions of source code must retain the above copyright
26        notice, this list of conditions and the following disclaimer.
27     2. Redistributions in binary form must reproduce the above copyright
28        notice, this list of conditions and the following disclaimer in the
29        documentation and/or other materials provided with the distribution.
30     3. The name of the author may not be used to endorse or promote products
31        derived from this software without specific prior written permission.
32 
33     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34     OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36     ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43     SUCH DAMAGE.
44 */
45 
46 /*
47  * tgafile.cpp - This file contains the code to write 24 bit targa files...
48  */
49 
50 #include "machine.hpp"
51 #include "types.hpp"
52 #include "util.hpp"
53 #include "ui.hpp"
54 #include "imageio.hpp"
55 #include "tgafile.hpp"
56 
createtgafile(char * name,unsigned short width,unsigned short height)57 void createtgafile(char *name, unsigned short width, unsigned short height) {
58     int filesize;
59     FILE *ofp;
60 
61     filesize = 3 * width * height + 18 - 10;
62 
63     if (name == nullptr)
64         std::exit(-1);
65     else {
66         ofp = fopen(name, "w+b");
67         if (ofp == nullptr) {
68             char msgtxt[2048];
69             sprintf(msgtxt, "Cannot create %s for output!", name);
70             rt_ui_message(MSG_ERR, msgtxt);
71             rt_ui_message(MSG_ABORT, "Rendering Aborted.");
72             std::exit(-1);
73         }
74 
75         fputc(0, ofp); /* IdLength      */
76         fputc(0, ofp); /* ColorMapType  */
77         fputc(2, ofp); /* ImageTypeCode */
78         fputc(0, ofp); /* ColorMapOrigin, low byte  */
79         fputc(0, ofp); /* ColorMapOrigin, high byte */
80         fputc(0, ofp); /* ColorMapLength, low byte  */
81         fputc(0, ofp); /* ColorMapLength, high byte */
82         fputc(0, ofp); /* ColorMapEntrySize  */
83         fputc(0, ofp); /* XOrigin, low byte  */
84         fputc(0, ofp); /* XOrigin, high byte */
85         fputc(0, ofp); /* YOrigin, low byte  */
86         fputc(0, ofp); /* YOrigin, high byte */
87         fputc((width & 0xff), ofp); /* Width, low byte */
88         fputc(((width >> 8) & 0xff), ofp); /* Width, high byte */
89         fputc((height & 0xff), ofp); /* Height, low byte */
90         fputc(((height >> 8) & 0xff), ofp); /* Height, high byte */
91         fputc(24, ofp); /* ImagePixelSize */
92         fputc(0x20, ofp); /* ImageDescriptorByte 0x20 == flip vertically */
93 
94         fseek(ofp, filesize, 0);
95         fprintf(ofp, "9876543210");
96 
97         fclose(ofp);
98     }
99 }
100 
opentgafile(char * filename)101 void *opentgafile(char *filename) {
102     FILE *ofp;
103 
104     ofp = fopen(filename, "r+b");
105     if (ofp == nullptr) {
106         char msgtxt[2048];
107         sprintf(msgtxt, "Cannot open %s for output!", filename);
108         rt_ui_message(MSG_ERR, msgtxt);
109         rt_ui_message(MSG_ABORT, "Rendering Aborted.");
110         std::exit(-1);
111     }
112 
113     return ofp;
114 }
115 
writetgaregion(void * voidofp,int iwidth,int iheight,int startx,int starty,int stopx,int stopy,char * buffer)116 void writetgaregion(void *voidofp,
117                     int iwidth,
118                     int iheight,
119                     int startx,
120                     int starty,
121                     int stopx,
122                     int stopy,
123                     char *buffer) {
124     int y, totalx, totaly;
125     char *bufpos;
126     long filepos;
127     std::size_t numbytes;
128     FILE *ofp = (FILE *)voidofp;
129 
130     totalx = stopx - startx + 1;
131     totaly = stopy - starty + 1;
132 
133     for (y = 0; y < totaly; y++) {
134         bufpos = buffer + (totalx * 3) * (totaly - y - 1);
135         filepos = 18 + iwidth * 3 * (iheight - starty - totaly + y + 1) + (startx - 1) * 3;
136 
137         if (filepos >= 18) {
138             fseek(ofp, filepos, 0);
139             numbytes = fwrite(bufpos, 3, totalx, ofp);
140 
141             if (numbytes != totalx) {
142                 char msgtxt[256];
143                 sprintf(msgtxt, "File write problem, %d bytes written.", (int)numbytes);
144                 rt_ui_message(MSG_ERR, msgtxt);
145             }
146         }
147         else {
148             rt_ui_message(MSG_ERR, "writetgaregion: file ptr out of range!!!\n");
149             return; /* don't try to continue */
150         }
151     }
152 }
153 
readtga(char * name,int * xres,int * yres,unsigned char ** imgdata)154 int readtga(char *name, int *xres, int *yres, unsigned char **imgdata) {
155     int format, width, height, w1, w2, h1, h2, depth, flags;
156     int imgsize, i, tmp;
157     std::size_t bytesread;
158     FILE *ifp;
159 
160     ifp = fopen(name, "r");
161     if (ifp == nullptr) {
162         return IMAGEBADFILE; /* couldn't open the file */
163     }
164 
165     /* read the targa header */
166     getc(ifp); /* ID length */
167     getc(ifp); /* colormap type */
168     format = getc(ifp); /* image type */
169     getc(ifp); /* color map origin */
170     getc(ifp); /* color map origin */
171     getc(ifp); /* color map length */
172     getc(ifp); /* color map length */
173     getc(ifp); /* color map entry size */
174     getc(ifp); /* x origin */
175     getc(ifp); /* x origin */
176     getc(ifp); /* y origin */
177     getc(ifp); /* y origin */
178     w1 = getc(ifp); /* width (low) */
179     w2 = getc(ifp); /* width (hi) */
180     h1 = getc(ifp); /* height (low) */
181     h2 = getc(ifp); /* height (hi) */
182     depth = getc(ifp); /* image pixel size */
183     flags = getc(ifp); /* image descriptor byte */
184 
185     if ((format != 2) || (depth != 24)) {
186         fclose(ifp);
187         return IMAGEUNSUP; /* unsupported targa format */
188     }
189 
190     width = ((w2 << 8) | w1);
191     height = ((h2 << 8) | h1);
192 
193     imgsize = 3 * width * height;
194     *imgdata = (unsigned char *)rt_getmem(imgsize);
195     bytesread = fread(*imgdata, 1, imgsize, ifp);
196     fclose(ifp);
197 
198     /* flip image vertically */
199     if (flags == 0x20) {
200         int rowsize = 3 * width;
201         unsigned char *copytmp;
202 
203         copytmp = (unsigned char *)malloc(rowsize);
204 
205         for (i = 0; i < height / 2; i++) {
206             memcpy(copytmp, &((*imgdata)[rowsize * i]), rowsize);
207             memcpy(&(*imgdata)[rowsize * i], &(*imgdata)[rowsize * (height - 1 - i)], rowsize);
208             memcpy(&(*imgdata)[rowsize * (height - 1 - i)], copytmp, rowsize);
209         }
210 
211         free(copytmp);
212     }
213 
214     /* convert from BGR order to RGB order */
215     for (i = 0; i < imgsize; i += 3) {
216         tmp = (*imgdata)[i]; /* Blue */
217         (*imgdata)[i] = (*imgdata)[i + 2]; /* Red */
218         (*imgdata)[i + 2] = tmp; /* Blue */
219     }
220 
221     *xres = width;
222     *yres = height;
223 
224     if (bytesread != imgsize)
225         return IMAGEREADERR;
226 
227     return IMAGENOERR;
228 }
229