]> git.vomp.tv Git - vompclient-marten.git/blob - wjpeg.h
*** empty log message ***
[vompclient-marten.git] / wjpeg.h
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #ifndef WJPEG_H
22 #define WJPEG_H
23
24 #include <stdio.h>
25 #include <malloc.h>
26
27 #ifdef WIN32
28
29 #include <winsock2.h>
30 #include <windows.h>
31
32
33 //#define NEED_FAR_POINTERS
34 #define XMD_H //workaround some compiling issues
35 #endif
36
37 class Surface;
38 class Boxx;
39
40 //a reader to be implemented by the caller
41 class JpegReader {
42   public:
43   //read the next chunk of jpeg data
44   //offset - from start of file
45   //len I buf len (max bytes to read)
46   //return read len, 0 on EOF, -1 on error, *buf set to buffer
47   //will be released with free(!!!) after decoding
48   virtual ULONG readChunk(ULONG offset,ULONG len,char **buf)=0;
49   //a callback when the drawing is complete
50   //the implementation is optional
51   virtual void drawingDone(){};
52   //get the size of the current picture
53   virtual ULONG getSize(){ return 0;}
54   virtual ~JpegReader(){};
55 };
56 class WJpeg : public Boxx
57 {
58   public:
59   
60     // temp for boxx
61     void setDimensions(int width, int height) {area.w=width;area.h=height;};
62   
63   
64     WJpeg();
65     virtual ~WJpeg();
66     //old style usage - load local file
67     //the sequence is init(filename), draw
68     //the new usage is drawJpeg (with having the right offsets computed)
69     int init(char* fileName);
70     void draw();
71
72     bool hasError();
73     
74     //mode for scaling pictures
75     enum ScaleMode {
76         LETTER=0,
77         CROP=1,
78         CROPPERCENT=2};
79     //rotations
80     enum Rotation{
81      ROT_0=0,
82      ROT_90=1,
83      ROT_180=2,
84      ROT_270=3
85     };
86     //jpeg info 
87     struct JpegControl {
88       public:
89       //the available drawing area
90       Region area;
91       bool enlarge;
92       //the maximum allowed scale factor after decompress
93       UINT scaleafter;
94       //the scale mode
95       enum ScaleMode mode;
96       //the size value if scaleMode==cropPercent
97       //%of the drawing area size
98       UINT  scaleAmount;
99       //the rotation (user defined as input)
100       //if exif rotation is found this will be added
101       enum Rotation rotation;
102
103       //paremeters filled during Jpeg parsing
104       enum Rotation exifRotation;
105       char exifDate[30];
106       char error[100];
107       UINT picw;
108       UINT pich;
109       ULONG compressedSize;
110
111       //parameters computed to display picture
112       enum Rotation finalRotation;
113       //scale in %
114       UINT scale;
115       JpegControl() {
116         area.x=0;
117         area.y=0;
118         area.w=0;
119         area.h=0;
120         enlarge=false;
121         scaleafter=3;
122         scaleAmount=110;
123         mode=CROPPERCENT;
124         rotation=ROT_0;
125         exifRotation=ROT_0;
126         finalRotation=ROT_0;
127         exifDate[0]='\0';
128         error[0]='\0';
129         picw=0;
130         pich=0;
131         compressedSize=0;
132         scale=100;
133       }
134     };
135
136     //the standalone drawing function
137     //this will draw into the provided surface
138     //the reader has to be initialized before
139     //calling this function does not need a WJpeg being instantiated
140     //it simply draws into the surface
141     bool static drawJpeg(JpegControl * control, Surface* sfc, JpegReader *rdr, Colour & backgroundColour);
142
143   private:
144     //our drawPixel with considers rotation
145     /* handle picture rotation
146        90: xr=h-y
147            yr=x
148        180:xr=w-x
149            yr=h-y
150        270:xr=y
151            yr=w-x
152     */
153     inline static void  drawPixel(Surface * sfc,enum Rotation rotate,int x, int y,int w,int h,int xpos, int ypos,Colour c){
154     int xb=0;
155     int yb=0;
156     switch(rotate) {
157        case ROT_0:
158           xb=x;
159           yb=y;
160           break;
161        case ROT_90:
162           xb=h-y;
163           yb=x;
164           break;
165        case ROT_180:
166           xb=w-x;
167           yb=h-y;
168           break;
169        case ROT_270:
170           xb=y;
171           yb=w-x;
172           break;
173        }
174        xb+=xpos;
175        yb+=ypos;
176        if (xb < 0 || yb < 0 ) {
177          return;
178        }
179        sfc->drawPixel((UINT)xb,(UINT)yb,c,true);
180     }
181
182     /**
183       draw a line of pixels coming from the decompressor
184       if scaleafter > 1 we draw that many lines (numlines is the# lines in the buffer)
185       picturew is the resulting width of the picture
186     **/  
187     inline static void drawLine(Surface *sfc,enum Rotation rotate, unsigned char *cp,UINT scaleafter,UINT picturew,UINT pictureh, 
188         UINT xpos, UINT ypos, UINT outy, UINT linelen,UINT pixeloffset, UINT numlines, UINT fac) {
189       Colour c;
190       for (UINT x = 0; x < picturew; x++)
191       {
192         if (scaleafter > 1 ) {
193            //boxfilter scalefactor*scalefactor
194            //take 0...scalefactor pixels in x and y direction
195            for (int colornum=0;colornum<3;colornum++) {
196              UINT comp=0;
197              unsigned char * accp=cp;
198              for (UINT rows=0;rows<scaleafter;rows++) {
199                unsigned char * pp=accp;
200                for (UINT cols=0;cols<scaleafter;cols++) {
201                  comp+=(UINT)*pp;
202                  if (pp-accp < (int)linelen-3) pp+=3;
203                  }
204                if (rows < numlines) accp+=linelen;
205                }
206              comp=(comp*fac) >> 10;
207              if (colornum == 0) c.red=comp;
208              if (colornum == 1) c.green=comp;
209              if (colornum == 2) c.blue=comp;
210              cp++;
211            }
212           
213         }
214         else {
215           c.red = *cp;cp++;
216           c.green = *cp;cp++;
217           c.blue = *cp;cp++;
218         }
219         cp+=pixeloffset;
220         drawPixel(sfc,rotate,x, outy, picturew,pictureh,xpos,ypos,c);
221       }
222     }
223     //find my own surface and fill the area with my x and y offset within
224     Surface * getSurface(Region &a);
225
226     JpegReader *reader;
227     bool owningReader;
228     char errbuf[200];
229 };
230
231 #endif