]> git.sesse.net Git - vlc/blob - modules/video_filter/atmo/AtmoZoneDefinition.cpp
Psyche/sharpen: Add chroma checks to prevent crashes
[vlc] / modules / video_filter / atmo / AtmoZoneDefinition.cpp
1
2 #ifdef HAVE_CONFIG_H
3 # include "config.h"
4 #endif
5
6 #include "AtmoDefs.h"
7
8 #if defined (WIN32)
9 #  include <windows.h>
10 #else
11 #  include <vlc_codecs.h>
12 #endif
13
14 #include <math.h>
15 #include <stdio.h>
16 #include "AtmoZoneDefinition.h"
17
18 CAtmoZoneDefinition::CAtmoZoneDefinition(void)
19 {
20 }
21
22 CAtmoZoneDefinition::~CAtmoZoneDefinition(void)
23 {
24 }
25
26 void CAtmoZoneDefinition::Fill(unsigned char value)
27 {
28   for(int i=0; i < IMAGE_SIZE; i++)
29       m_BasicWeight[i] = value;
30 }
31
32
33 // max weight to left
34 void CAtmoZoneDefinition::FillGradientFromLeft(int start_row,int end_row)
35 {
36    int index;
37    unsigned char col_norm;
38    index = start_row * CAP_WIDTH;
39    for(int row=start_row; row < end_row; row++) {
40        for(int col=0; col < CAP_WIDTH; col++) {
41            // should be a value between 0 .. 255?
42            col_norm = (255 * (CAP_WIDTH-col-1)) / (CAP_WIDTH-1);
43            m_BasicWeight[index++] = col_norm;
44        }
45    }
46 }
47
48 // max weight to right
49 void CAtmoZoneDefinition::FillGradientFromRight(int start_row,int end_row)
50 {
51    int index;
52    unsigned char col_norm;
53    index = start_row * CAP_WIDTH;
54    for(int row=start_row; row < end_row; row++) {
55       for(int col=0; col < CAP_WIDTH; col++) {
56           col_norm = (255 * col) / (CAP_WIDTH-1); // should be a value between 0 .. 255?
57           m_BasicWeight[index++] = col_norm;
58        }
59    }
60 }
61
62 // max weight from top
63 void CAtmoZoneDefinition::FillGradientFromTop(int start_col,int end_col)
64 {
65    int index;
66    unsigned char row_norm;
67
68    for(int row=0; row < CAP_HEIGHT; row++) {
69        index = row * CAP_WIDTH + start_col;
70
71        row_norm = (255 * (CAP_HEIGHT-row-1)) / (CAP_HEIGHT-1); // should be a value between 0 .. 255?
72        for(int col=start_col; col < end_col; col++) {
73            m_BasicWeight[index++] = row_norm;
74        }
75    }
76 }
77
78 // max weight from bottom
79 void CAtmoZoneDefinition::FillGradientFromBottom(int start_col,int end_col)
80 {
81    int index;
82    unsigned char row_norm;
83    for(int row=0; row < CAP_HEIGHT; row++) {
84        index = row * CAP_WIDTH + start_col;
85        row_norm = (255 * row) / (CAP_HEIGHT-1); // should be a value between 0 .. 255?
86        for(int col=start_col; col < end_col; col++) {
87            m_BasicWeight[index++] = row_norm;
88        }
89    }
90 }
91
92 #if !defined(_ATMO_VLC_PLUGIN_)
93
94 void CAtmoZoneDefinition::SaveZoneBitmap(char *fileName)
95 {
96      if(!fileName) return;
97
98      BITMAPINFO bmpInfo;
99      // BITMAPINFOHEADER
100      BITMAPFILEHEADER  bmpFileHeader;
101      ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
102      bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
103
104
105      bmpInfo.bmiHeader.biHeight = -CAP_HEIGHT;
106      bmpInfo.bmiHeader.biWidth  = CAP_WIDTH;
107      bmpInfo.bmiHeader.biSizeImage = abs(bmpInfo.bmiHeader.biHeight) * bmpInfo.bmiHeader.biWidth * 3;
108
109      unsigned char *pBuf = (unsigned char *)malloc(bmpInfo.bmiHeader.biSizeImage);
110      for(int y=0; y < CAP_HEIGHT; y++ )
111      {
112          for(int x=0; x < CAP_WIDTH; x++)
113          {
114              pBuf[y * CAP_WIDTH * 3 + x * 3 ] = 0;
115              pBuf[y * CAP_WIDTH * 3 + x * 3 + 1 ] = m_BasicWeight[y * CAP_WIDTH + x];
116              pBuf[y * CAP_WIDTH * 3 + x * 3 + 2] = 0;
117          }
118      }
119
120      bmpInfo.bmiHeader.biCompression = BI_RGB;
121      bmpInfo.bmiHeader.biPlanes = 1;
122      bmpInfo.bmiHeader.biBitCount = 24;
123
124      bmpFileHeader.bfReserved1=0;
125      bmpFileHeader.bfReserved2=0;
126      bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
127      bmpFileHeader.bfType = MakeIntelWord('M','B');
128      bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
129
130
131      FILE *fp = NULL;
132      fp = fopen(fileName,"wb");
133      fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
134      fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
135      fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp);
136      fclose(fp);
137 }
138
139 void CAtmoZoneDefinition::SaveWeightBitmap(char *fileName,int *weight)
140 {
141      if(!fileName || !weight) return;
142
143      BITMAPINFO bmpInfo;
144      // BITMAPINFOHEADER
145      BITMAPFILEHEADER  bmpFileHeader;
146      ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
147      bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
148
149
150      bmpInfo.bmiHeader.biHeight = -CAP_HEIGHT;
151      bmpInfo.bmiHeader.biWidth  = CAP_WIDTH;
152      bmpInfo.bmiHeader.biSizeImage = abs(bmpInfo.bmiHeader.biHeight) * bmpInfo.bmiHeader.biWidth * 3;
153
154      unsigned char *pBuf = (unsigned char *)malloc(bmpInfo.bmiHeader.biSizeImage);
155      for(int y=0; y < CAP_HEIGHT; y++ )
156      {
157          for(int x=0; x < CAP_WIDTH; x++)
158          {
159              pBuf[y * CAP_WIDTH * 3 + x * 3 ] = 0;
160              pBuf[y * CAP_WIDTH * 3 + x * 3 + 1 ] = (unsigned char)weight[y * CAP_WIDTH + x];
161              pBuf[y * CAP_WIDTH * 3 + x * 3 + 2] = 0;
162          }
163      }
164
165      bmpInfo.bmiHeader.biCompression = BI_RGB;
166      bmpInfo.bmiHeader.biPlanes = 1;
167      bmpInfo.bmiHeader.biBitCount = 24;
168
169      bmpFileHeader.bfReserved1=0;
170      bmpFileHeader.bfReserved2=0;
171      bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
172      bmpFileHeader.bfType = MakeIntelWord('M','B');
173      bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
174
175
176      FILE *fp = NULL;
177      fp = fopen(fileName,"wb");
178      fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
179      fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
180      fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp);
181      fclose(fp);
182 }
183
184
185 #endif
186
187
188
189 int CAtmoZoneDefinition::LoadGradientFromBitmap(char *pszBitmap)
190 {
191   // transform 256 color image (gray scale!)
192   // into m_basicWeight or use the GREEN value of a 24bit image!
193   // channel of a true color bitmap!
194   BITMAPINFO bmpInfo;
195   BITMAPFILEHEADER  bmpFileHeader;
196
197   /*
198   ATMO_LOAD_GRADIENT_FILENOTFOND
199 #define ATMO_LOAD_GRADIENT_OK  0
200 #define ATMO_LOAD_GRADIENT_FAILED_SIZE    1
201 #define ATMO_LOAD_GRADIENT_FAILED_HEADER  2
202   */
203
204
205    FILE *bmp = fopen(pszBitmap, "rb");
206    if(!bmp)
207     return ATMO_LOAD_GRADIENT_FILENOTFOND;
208
209     if(fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, bmp) != 1)
210     {
211         fclose(bmp);
212         return ATMO_LOAD_GRADIENT_FAILED_SIZE;
213     }
214
215     if(bmpFileHeader.bfType != MakeIntelWord('M','B'))
216     {
217         fclose(bmp);
218         return ATMO_LOAD_GRADIENT_FAILED_HEADER;
219     }
220
221     if(fread(&bmpInfo, sizeof(BITMAPINFO), 1, bmp) != 1)
222     {
223         fclose(bmp);
224         return ATMO_LOAD_GRADIENT_FAILED_SIZE;
225     }
226
227     if(bmpInfo.bmiHeader.biCompression != BI_RGB)
228     {
229         fclose(bmp);
230         return ATMO_LOAD_GRADIENT_FAILED_FORMAT;
231     }
232     if((bmpInfo.bmiHeader.biBitCount != 8) && (bmpInfo.bmiHeader.biBitCount != 24))
233     {
234         fclose(bmp);
235         return ATMO_LOAD_GRADIENT_FAILED_FORMAT;
236     }
237
238     int width = bmpInfo.bmiHeader.biWidth;
239     int height = bmpInfo.bmiHeader.biHeight;
240     ATMO_BOOL invertDirection = (height > 0);
241     height = abs(height);
242     if((width != CAP_WIDTH) || (height != CAP_HEIGHT))
243     {
244         fclose(bmp);
245         return ATMO_LOAD_GRADIENT_FAILED_SIZE;
246     }
247
248     fseek(bmp, bmpFileHeader.bfOffBits, SEEK_SET);
249
250     int imageSize = width * height * bmpInfo.bmiHeader.biBitCount/8;
251
252     unsigned char *pixelBuffer = (unsigned char *)malloc(imageSize);
253     if(fread(pixelBuffer,imageSize,1,bmp) != 1)
254     {
255         fclose(bmp);
256         return ATMO_LOAD_GRADIENT_FAILED_SIZE;
257     }
258
259     if(bmpInfo.bmiHeader.biBitCount == 8)
260     {
261         int ydest;
262         for(int y=0;y < CAP_HEIGHT; y++) {
263             if(invertDirection) {
264                 ydest = (CAP_HEIGHT - y - 1);
265             } else {
266                 ydest = y;
267             }
268             for(int x=0;x < CAP_WIDTH; x++) {
269                 // palette should be grey scale - so that index 0 is black and
270                 // index 255 means white!
271                 // everything else would produce funny results!
272                 m_BasicWeight[ydest * CAP_WIDTH + x] =
273                     pixelBuffer[y * CAP_WIDTH + x];
274             }
275         }
276     }
277
278     if(bmpInfo.bmiHeader.biBitCount == 24)
279     {
280         int ydest;
281         for(int y=0;y < CAP_HEIGHT; y++) {
282             if(invertDirection) {
283                 ydest = (CAP_HEIGHT - y - 1);
284             } else {
285                 ydest = y;
286             }
287             for(int x=0;x < CAP_WIDTH; x++) {
288                 // use the green value as reference...
289                 m_BasicWeight[ydest * CAP_WIDTH + x] =
290                     pixelBuffer[y * CAP_WIDTH * 3 + (x*3) + 1 ];
291             }
292         }
293     }
294     free(pixelBuffer);
295     fclose(bmp);
296
297     return ATMO_LOAD_GRADIENT_OK;
298 }
299
300
301 void CAtmoZoneDefinition::UpdateWeighting(int *destWeight,
302                                           int WidescreenMode,
303                                           int newEdgeWeightning)
304 {
305   /*
306     use the values in m_BasicWeight and newWeightning to
307     update the direct control array for the output thread!
308   */
309
310   int index = 0;
311   for(int row=0; row < CAP_HEIGHT; row++) {
312       for(int col=0; col < CAP_WIDTH; col++) {
313           if ((WidescreenMode == 1) && ((row <= CAP_HEIGHT/8) || (row >= (7*CAP_HEIGHT)/8)))
314           {
315              destWeight[index] = 0;
316           } else {
317                      destWeight[index] = (int)(255.0 * (float)pow( ((float)m_BasicWeight[index])/255.0 , newEdgeWeightning));
318           }
319           index++;
320       }
321   }
322 }
323
324 void CAtmoZoneDefinition::setZoneNumber(int num)
325 {
326     m_zonenumber = num;
327 }
328
329 int CAtmoZoneDefinition::getZoneNumber()
330 {
331     return m_zonenumber;
332 }
333
334