Merge branch 'blender2.7'
[blender.git] / source / blender / avi / intern / avi_rgb.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file \ingroup avi
21  *
22  * This is external code. Converts rgb-type avi-s.
23  */
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "AVI_avi.h"
31 #include "avi_rgb.h"
32
33 #include "IMB_imbuf.h"
34
35 /* implementation */
36
37 void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, unsigned char *buffer, size_t *size)
38 {
39         unsigned char *buf;
40         AviBitmapInfoHeader *bi;
41         short bits = 32;
42
43         (void)size; /* unused */
44
45         bi = (AviBitmapInfoHeader *) movie->streams[stream].sf;
46         if (bi) bits = bi->BitCount;
47
48         if (bits == 16) {
49                 unsigned short *pxl;
50                 unsigned char *to;
51 #ifdef __BIG_ENDIAN__
52                 unsigned char  *pxla;
53 #endif
54
55                 buf = imb_alloc_pixels(movie->header->Height, movie->header->Width, 3, sizeof(unsigned char),  "fromavirgbbuf");
56
57                 if (buf) {
58                         size_t y = movie->header->Height;
59                         to = buf;
60
61                         while (y--) {
62                                 pxl = (unsigned short *) (buffer + y * movie->header->Width * 2);
63
64 #ifdef __BIG_ENDIAN__
65                                 pxla = (unsigned char *)pxl;
66 #endif
67
68                                 size_t x = movie->header->Width;
69                                 while (x--) {
70 #ifdef __BIG_ENDIAN__
71                                         int i = pxla[0];
72                                         pxla[0] = pxla[1];
73                                         pxla[1] = i;
74
75                                         pxla += 2;
76 #endif
77
78                                         *(to++) = ((*pxl >> 10) & 0x1f) * 8;
79                                         *(to++) = ((*pxl >> 5) & 0x1f) * 8;
80                                         *(to++) = (*pxl & 0x1f) * 8;
81                                         pxl++;
82                                 }
83                         }
84                 }
85
86                 MEM_freeN(buffer);
87
88                 return buf;
89         }
90         else {
91                 buf = imb_alloc_pixels(movie->header->Height, movie->header->Width, 3, sizeof(unsigned char),  "fromavirgbbuf");
92
93                 if (buf) {
94                         size_t rowstride = movie->header->Width * 3;
95                         if ((bits != 16) && (movie->header->Width % 2)) rowstride++;
96
97                         for (size_t y = 0; y < movie->header->Height; y++) {
98                                 memcpy(&buf[y * movie->header->Width * 3], &buffer[((movie->header->Height - 1) - y) * rowstride], movie->header->Width * 3);
99                         }
100
101                         for (size_t y = 0; y < (size_t)movie->header->Height * (size_t)movie->header->Width * 3; y += 3) {
102                                 int i = buf[y];
103                                 buf[y] = buf[y + 2];
104                                 buf[y + 2] = i;
105                         }
106                 }
107
108                 MEM_freeN(buffer);
109
110                 return buf;
111         }
112 }
113
114 void *avi_converter_to_avi_rgb(AviMovie *movie, int stream, unsigned char *buffer, size_t *size)
115 {
116         unsigned char *buf;
117
118         (void)stream; /* unused */
119
120         size_t rowstride = movie->header->Width * 3;
121         /* AVI files has uncompressed lines 4-byte aligned */
122         rowstride = (rowstride + 3) & ~3;
123
124         *size = movie->header->Height * rowstride;
125         buf = MEM_mallocN(*size, "toavirgbbuf");
126
127         for (size_t y = 0; y < movie->header->Height; y++) {
128                 memcpy(&buf[y * rowstride], &buffer[((movie->header->Height - 1) - y) * movie->header->Width * 3], movie->header->Width * 3);
129         }
130
131         for (size_t y = 0; y < movie->header->Height; y++) {
132                 for (size_t x = 0; x < movie->header->Width * 3; x += 3) {
133                         int i = buf[y * rowstride + x];
134                         buf[y * rowstride + x] = buf[y * rowstride + x + 2];
135                         buf[y * rowstride + x + 2] = i;
136                 }
137         }
138
139         MEM_freeN(buffer);
140
141         return buf;
142 }