1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
32 #include "allobjects.h"
33 #include "modsupport.h" /* For getargs() etc. */
34 #include "ceval.h" /* For call_object() */
38 int ob_isCompressor
; /* Compressor or Decompressor */
39 CL_Handle ob_compressorHdl
;
44 static object
*ClError
; /* exception cl.error */
46 static int error_handler_called
= 0;
49 * We want to use the function prototypes that are available in the C
50 * compiler on the SGI. Because of that, we need to declare the first
51 * argument of the compressor and decompressor methods as "object *",
52 * even though they are really "clobject *". Therefore we cast the
53 * argument to the proper type using this macro.
55 #define SELF ((clobject *) self)
57 /********************************************************************
59 ********************************************************************/
61 cl_ErrorHandler(CL_Handle handle
, int code
, const char *fmt
, ...)
64 char errbuf
[BUFSIZ
]; /* hopefully big enough */
67 if (err_occurred()) /* don't change existing error */
69 error_handler_called
= 1;
71 vsprintf(errbuf
, fmt
, ap
);
73 p
= &errbuf
[strlen(errbuf
) - 1]; /* swat the line feed */
76 err_setstr(ClError
, errbuf
);
80 * This assumes that params are always in the range 0 to some maximum.
83 param_type_is_float(clobject
*self
, int param
)
88 if (self
->ob_paramtypes
== NULL
) {
89 error_handler_called
= 0;
90 bufferlength
= clQueryParams(self
->ob_compressorHdl
, 0, 0);
91 if (error_handler_called
)
94 self
->ob_paramtypes
= NEW(int, bufferlength
);
95 if (self
->ob_paramtypes
== NULL
)
97 self
->ob_nparams
= bufferlength
/ 2;
99 (void) clQueryParams(self
->ob_compressorHdl
, self
->ob_paramtypes
, bufferlength
);
100 if (error_handler_called
) {
101 DEL(self
->ob_paramtypes
);
102 self
->ob_paramtypes
= NULL
;
107 if (param
< 0 || param
>= self
->ob_nparams
)
110 if (self
->ob_paramtypes
[param
*2 + 1] == CL_FLOATING_ENUM_VALUE
||
111 self
->ob_paramtypes
[param
*2 + 1] == CL_FLOATING_RANGE_VALUE
)
117 /********************************************************************
118 Single image compression/decompression.
119 ********************************************************************/
121 cl_CompressImage(object
*self
, object
*args
)
123 int compressionScheme
, width
, height
, originalFormat
;
124 float compressionRatio
;
125 int frameBufferSize
, compressedBufferSize
;
127 object
*compressedBuffer
;
129 if (!getargs(args
, "(iiiifs#)", &compressionScheme
, &width
, &height
,
130 &originalFormat
, &compressionRatio
, &frameBuffer
,
135 compressedBuffer
= newsizedstringobject(NULL
, frameBufferSize
);
136 if (compressedBuffer
== NULL
)
139 compressedBufferSize
= frameBufferSize
;
140 error_handler_called
= 0;
141 if (clCompressImage(compressionScheme
, width
, height
, originalFormat
,
142 compressionRatio
, (void *) frameBuffer
,
143 &compressedBufferSize
,
144 (void *) getstringvalue(compressedBuffer
))
146 DECREF(compressedBuffer
);
147 if (!error_handler_called
)
148 err_setstr(ClError
, "clCompressImage failed");
152 if (compressedBufferSize
> frameBufferSize
) {
153 frameBufferSize
= compressedBufferSize
;
154 DECREF(compressedBuffer
);
158 if (compressedBufferSize
< frameBufferSize
)
159 if (resizestring(&compressedBuffer
, compressedBufferSize
))
162 return compressedBuffer
;
166 cl_DecompressImage(object
*self
, object
*args
)
168 int compressionScheme
, width
, height
, originalFormat
;
169 char *compressedBuffer
;
170 int compressedBufferSize
, frameBufferSize
;
173 if (!getargs(args
, "(iiiis#)", &compressionScheme
, &width
, &height
,
174 &originalFormat
, &compressedBuffer
,
175 &compressedBufferSize
))
178 frameBufferSize
= width
* height
* CL_BytesPerPixel(originalFormat
);
180 frameBuffer
= newsizedstringobject(NULL
, frameBufferSize
);
181 if (frameBuffer
== NULL
)
184 error_handler_called
= 0;
185 if (clDecompressImage(compressionScheme
, width
, height
, originalFormat
,
186 compressedBufferSize
, compressedBuffer
,
187 (void *) getstringvalue(frameBuffer
)) == FAILURE
) {
189 if (!error_handler_called
)
190 err_setstr(ClError
, "clDecompressImage failed");
197 /********************************************************************
198 Sequential compression/decompression.
199 ********************************************************************/
200 #define CheckCompressor(self) if ((self)->ob_compressorHdl == NULL) { \
201 err_setstr(RuntimeError, "(de)compressor not active"); \
206 doClose(clobject
*self
, object
*args
, int (*close_func
)(CL_Handle
))
208 CheckCompressor(self
);
213 error_handler_called
= 0;
214 if ((*close_func
)(self
->ob_compressorHdl
) == FAILURE
) {
215 if (!error_handler_called
)
216 err_setstr(ClError
, "close failed");
220 self
->ob_compressorHdl
= NULL
;
222 if (self
->ob_paramtypes
)
223 DEL(self
->ob_paramtypes
);
224 self
->ob_paramtypes
= NULL
;
231 clm_CloseCompressor(object
*self
, object
*args
)
233 return doClose(SELF
, args
, clCloseCompressor
);
237 clm_CloseDecompressor(object
*self
, object
*args
)
239 return doClose(SELF
, args
, clCloseDecompressor
);
243 clm_Compress(object
*self
, object
*args
)
246 int frameBufferSize
, compressedBufferSize
, size
;
250 CheckCompressor(SELF
);
252 if (!getargs(args
, "(is#)", &numberOfFrames
, &frameBuffer
, &frameBufferSize
))
255 error_handler_called
= 0;
256 size
= clGetParam(SELF
->ob_compressorHdl
, CL_COMPRESSED_BUFFER_SIZE
);
257 compressedBufferSize
= size
;
258 if (error_handler_called
)
261 data
= newsizedstringobject(NULL
, size
);
265 error_handler_called
= 0;
266 if (clCompress(SELF
->ob_compressorHdl
, numberOfFrames
,
267 (void *) frameBuffer
, &compressedBufferSize
,
268 (void *) getstringvalue(data
)) == FAILURE
) {
270 if (!error_handler_called
)
271 err_setstr(ClError
, "compress failed");
275 if (compressedBufferSize
< size
)
276 if (resizestring(&data
, compressedBufferSize
))
279 if (compressedBufferSize
> size
) {
280 /* we didn't get all "compressed" data */
282 err_setstr(ClError
, "compressed data is more than fitted");
290 clm_Decompress(object
*self
, object
*args
)
294 char *compressedData
;
295 int compressedDataSize
, dataSize
;
297 CheckCompressor(SELF
);
299 if (!getargs(args
, "(is#)", &numberOfFrames
, &compressedData
,
300 &compressedDataSize
))
303 error_handler_called
= 0;
304 dataSize
= clGetParam(SELF
->ob_compressorHdl
, CL_FRAME_BUFFER_SIZE
);
305 if (error_handler_called
)
308 data
= newsizedstringobject(NULL
, dataSize
);
312 error_handler_called
= 0;
313 if (clDecompress(SELF
->ob_compressorHdl
, numberOfFrames
,
314 compressedDataSize
, (void *) compressedData
,
315 (void *) getstringvalue(data
)) == FAILURE
) {
317 if (!error_handler_called
)
318 err_setstr(ClError
, "decompress failed");
326 doParams(clobject
*self
, object
*args
, int (*func
)(CL_Handle
, int *, int),
335 CheckCompressor(self
);
337 if (!getargs(args
, "O", &list
))
339 if (!is_listobject(list
)) {
343 length
= getlistsize(list
);
344 PVbuffer
= NEW(int, length
);
345 if (PVbuffer
== NULL
)
347 for (i
= 0; i
< length
; i
++) {
348 v
= getlistitem(list
, i
);
349 if (is_floatobject(v
)) {
350 number
= getfloatvalue(v
);
351 PVbuffer
[i
] = CL_TypeIsInt(number
);
352 } else if (is_intobject(v
)) {
353 PVbuffer
[i
] = getintvalue(v
);
355 param_type_is_float(self
, PVbuffer
[i
-1]) > 0) {
356 number
= PVbuffer
[i
];
357 PVbuffer
[i
] = CL_TypeIsInt(number
);
366 error_handler_called
= 0;
367 (*func
)(self
->ob_compressorHdl
, PVbuffer
, length
);
368 if (error_handler_called
) {
374 for (i
= 0; i
< length
; i
++) {
376 param_type_is_float(self
, PVbuffer
[i
-1]) > 0) {
377 number
= CL_TypeIsFloat(PVbuffer
[i
]);
378 v
= newfloatobject(number
);
380 v
= newintobject(PVbuffer
[i
]);
381 setlistitem(list
, i
, v
);
392 clm_GetParams(object
*self
, object
*args
)
394 return doParams(SELF
, args
, clGetParams
, 1);
398 clm_SetParams(object
*self
, object
*args
)
400 return doParams(SELF
, args
, clSetParams
, 0);
404 do_get(clobject
*self
, object
*args
, int (*func
)(CL_Handle
, int))
409 CheckCompressor(self
);
411 if (!getargs(args
, "i", ¶mID
))
414 error_handler_called
= 0;
415 value
= (*func
)(self
->ob_compressorHdl
, paramID
);
416 if (error_handler_called
)
419 if (param_type_is_float(self
, paramID
) > 0) {
420 fvalue
= CL_TypeIsFloat(value
);
421 return newfloatobject(fvalue
);
424 return newintobject(value
);
428 clm_GetParam(object
*self
, object
*args
)
430 return do_get(SELF
, args
, clGetParam
);
434 clm_GetDefault(object
*self
, object
*args
)
436 return do_get(SELF
, args
, clGetDefault
);
440 clm_SetParam(object
*self
, object
*args
)
445 CheckCompressor(SELF
);
447 if (!getargs(args
, "(ii)", ¶mID
, &value
)) {
449 if (!getargs(args
, "(if)", ¶mID
, &fvalue
)) {
451 err_setstr(TypeError
, "bad argument list (format '(ii)' or '(if)')");
454 value
= CL_TypeIsInt(fvalue
);
456 if (param_type_is_float(SELF
, paramID
) > 0) {
458 value
= CL_TypeIsInt(fvalue
);
462 error_handler_called
= 0;
463 value
= clSetParam(SELF
->ob_compressorHdl
, paramID
, value
);
464 if (error_handler_called
)
467 if (param_type_is_float(SELF
, paramID
) > 0)
468 return newfloatobject(CL_TypeIsFloat(value
));
470 return newintobject(value
);
474 clm_GetParamID(object
*self
, object
*args
)
479 CheckCompressor(SELF
);
481 if (!getargs(args
, "s", &name
))
484 error_handler_called
= 0;
485 value
= clGetParamID(SELF
->ob_compressorHdl
, name
);
486 if (value
== FAILURE
) {
487 if (!error_handler_called
)
488 err_setstr(ClError
, "getparamid failed");
492 return newintobject(value
);
496 clm_QueryParams(object
*self
, object
*args
)
503 CheckCompressor(SELF
);
508 error_handler_called
= 0;
509 bufferlength
= clQueryParams(SELF
->ob_compressorHdl
, 0, 0);
510 if (error_handler_called
)
513 PVbuffer
= NEW(int, bufferlength
);
514 if (PVbuffer
== NULL
)
517 bufferlength
= clQueryParams(SELF
->ob_compressorHdl
, PVbuffer
,
519 if (error_handler_called
) {
524 list
= newlistobject(bufferlength
);
530 for (i
= 0; i
< bufferlength
; i
++) {
532 setlistitem(list
, i
, newintobject(PVbuffer
[i
]));
533 else if (PVbuffer
[i
] == 0) {
535 setlistitem(list
, i
, None
);
537 setlistitem(list
, i
, newstringobject((char *) PVbuffer
[i
]));
546 clm_GetMinMax(object
*self
, object
*args
)
551 CheckCompressor(SELF
);
553 if (!getargs(args
, "i", ¶m
))
556 clGetMinMax(SELF
->ob_compressorHdl
, param
, &min
, &max
);
558 if (param_type_is_float(SELF
, param
) > 0) {
559 fmin
= CL_TypeIsFloat(min
);
560 fmax
= CL_TypeIsFloat(max
);
561 return mkvalue("(ff)", fmin
, fmax
);
564 return mkvalue("(ii)", min
, max
);
568 clm_GetName(object
*self
, object
*args
)
573 CheckCompressor(SELF
);
575 if (!getargs(args
, "i", ¶m
))
578 error_handler_called
= 0;
579 name
= clGetName(SELF
->ob_compressorHdl
, param
);
580 if (name
== NULL
|| error_handler_called
) {
581 if (!error_handler_called
)
582 err_setstr(ClError
, "getname failed");
586 return newstringobject(name
);
590 clm_QuerySchemeFromHandle(object
*self
, object
*args
)
592 CheckCompressor(SELF
);
597 return newintobject(clQuerySchemeFromHandle(SELF
->ob_compressorHdl
));
601 clm_ReadHeader(object
*self
, object
*args
)
606 CheckCompressor(SELF
);
608 if (!getargs(args
, "s#", &header
, &headerSize
))
611 return newintobject(clReadHeader(SELF
->ob_compressorHdl
,
612 headerSize
, header
));
615 static struct methodlist compressor_methods
[] = {
616 {"close", clm_CloseCompressor
}, /* alias */
617 {"CloseCompressor", clm_CloseCompressor
},
618 {"Compress", clm_Compress
},
619 {"GetDefault", clm_GetDefault
},
620 {"GetMinMax", clm_GetMinMax
},
621 {"GetName", clm_GetName
},
622 {"GetParam", clm_GetParam
},
623 {"GetParamID", clm_GetParamID
},
624 {"GetParams", clm_GetParams
},
625 {"QueryParams", clm_QueryParams
},
626 {"QuerySchemeFromHandle",clm_QuerySchemeFromHandle
},
627 {"SetParam", clm_SetParam
},
628 {"SetParams", clm_SetParams
},
629 {NULL
, NULL
} /* sentinel */
632 static struct methodlist decompressor_methods
[] = {
633 {"close", clm_CloseDecompressor
}, /* alias */
634 {"CloseDecompressor", clm_CloseDecompressor
},
635 {"Decompress", clm_Decompress
},
636 {"GetDefault", clm_GetDefault
},
637 {"GetMinMax", clm_GetMinMax
},
638 {"GetName", clm_GetName
},
639 {"GetParam", clm_GetParam
},
640 {"GetParamID", clm_GetParamID
},
641 {"GetParams", clm_GetParams
},
642 {"ReadHeader", clm_ReadHeader
},
643 {"QueryParams", clm_QueryParams
},
644 {"QuerySchemeFromHandle",clm_QuerySchemeFromHandle
},
645 {"SetParam", clm_SetParam
},
646 {"SetParams", clm_SetParams
},
647 {NULL
, NULL
} /* sentinel */
651 cl_dealloc(object
*self
)
653 if (SELF
->ob_compressorHdl
) {
654 if (SELF
->ob_isCompressor
)
655 clCloseCompressor(SELF
->ob_compressorHdl
);
657 clCloseDecompressor(SELF
->ob_compressorHdl
);
663 cl_getattr(object
*self
, char *name
)
665 if (SELF
->ob_isCompressor
)
666 return findmethod(compressor_methods
, self
, name
);
668 return findmethod(decompressor_methods
, self
, name
);
671 static typeobject Cltype
= {
672 OB_HEAD_INIT(&Typetype
)
675 sizeof(clobject
), /*tp_size*/
678 (destructor
)cl_dealloc
, /*tp_dealloc*/
680 (getattrfunc
)cl_getattr
, /*tp_getattr*/
685 0, /*tp_as_sequence*/
690 doOpen(object
*self
, object
*args
, int (*open_func
)(int, CL_Handle
*),
696 if (!getargs(args
, "i", &scheme
))
699 new = NEWOBJ(clobject
, &Cltype
);
703 new->ob_compressorHdl
= NULL
;
704 new->ob_isCompressor
= iscompressor
;
705 new->ob_paramtypes
= NULL
;
707 error_handler_called
= 0;
708 if ((*open_func
)(scheme
, &new->ob_compressorHdl
) == FAILURE
) {
710 if (!error_handler_called
)
711 err_setstr(ClError
, "Open(De)Compressor failed");
714 return (object
*)new;
718 cl_OpenCompressor(object
*self
, object
*args
)
720 return doOpen(self
, args
, clOpenCompressor
, 1);
724 cl_OpenDecompressor(object
*self
, object
*args
)
726 return doOpen(self
, args
, clOpenDecompressor
, 0);
730 cl_QueryScheme(object
*self
, object
*args
)
736 if (!getargs(args
, "s#", &header
, &headerlen
))
739 scheme
= clQueryScheme(header
);
741 err_setstr(ClError
, "unknown compression scheme");
745 return newintobject(scheme
);
749 cl_QueryMaxHeaderSize(object
*self
, object
*args
)
753 if (!getargs(args
, "i", &scheme
))
756 return newintobject(clQueryMaxHeaderSize(scheme
));
760 cl_QueryAlgorithms(object
*self
, object
*args
)
762 int algorithmMediaType
;
768 if (!getargs(args
, "i", &algorithmMediaType
))
771 error_handler_called
= 0;
772 bufferlength
= clQueryAlgorithms(algorithmMediaType
, 0, 0);
773 if (error_handler_called
)
776 PVbuffer
= NEW(int, bufferlength
);
777 if (PVbuffer
== NULL
)
780 bufferlength
= clQueryAlgorithms(algorithmMediaType
, PVbuffer
,
782 if (error_handler_called
) {
787 list
= newlistobject(bufferlength
);
793 for (i
= 0; i
< bufferlength
; i
++) {
795 setlistitem(list
, i
, newintobject(PVbuffer
[i
]));
796 else if (PVbuffer
[i
] == 0) {
798 setlistitem(list
, i
, None
);
800 setlistitem(list
, i
, newstringobject((char *) PVbuffer
[i
]));
809 cl_QuerySchemeFromName(object
*self
, object
*args
)
811 int algorithmMediaType
;
815 if (!getargs(args
, "(is)", &algorithmMediaType
, &name
))
818 error_handler_called
= 0;
819 scheme
= clQuerySchemeFromName(algorithmMediaType
, name
);
820 if (error_handler_called
) {
821 err_setstr(ClError
, "unknown compression scheme");
825 return newintobject(scheme
);
829 cl_GetAlgorithmName(object
*self
, object
*args
)
834 if (!getargs(args
, "i", &scheme
))
837 name
= clGetAlgorithmName(scheme
);
839 err_setstr(ClError
, "unknown compression scheme");
843 return newstringobject(name
);
847 do_set(object
*self
, object
*args
, int (*func
)(int, int, int))
849 int scheme
, paramID
, value
;
853 if (!getargs(args
, "(iii)", &scheme
, ¶mID
, &value
)) {
855 if (!getargs(args
, "(iif)", &scheme
, ¶mID
, &fvalue
)) {
857 err_setstr(TypeError
, "bad argument list (format '(iii)' or '(iif)')");
860 value
= CL_TypeIsInt(fvalue
);
863 /* check some parameters which we know to be floats */
865 case CL_COMPRESSION_RATIO
:
868 value
= CL_TypeIsInt(fvalue
);
874 error_handler_called
= 0;
875 value
= (*func
)(scheme
, paramID
, value
);
876 if (error_handler_called
)
880 return newfloatobject(CL_TypeIsFloat(value
));
882 return newintobject(value
);
886 cl_SetDefault(object
*self
, object
*args
)
888 return do_set(self
, args
, clSetDefault
);
892 cl_SetMin(object
*self
, object
*args
)
894 return do_set(self
, args
, clSetMin
);
898 cl_SetMax(object
*self
, object
*args
)
900 return do_set(self
, args
, clSetMax
);
905 cvt_type(object
*self
, object
*args
)
910 if (getargs(args
, "i", &number
))
911 return newfloatobject(CL_TypeIsFloat(number
));
914 if (getargs(args
, "f", &fnumber
))
915 return newintobject(CL_TypeIsInt(fnumber
));
921 static struct methodlist cl_methods
[] = {
922 {"CompressImage", cl_CompressImage
},
923 {"DecompressImage", cl_DecompressImage
},
924 {"GetAlgorithmName", cl_GetAlgorithmName
},
925 {"OpenCompressor", cl_OpenCompressor
},
926 {"OpenDecompressor", cl_OpenDecompressor
},
927 {"QueryAlgorithms", cl_QueryAlgorithms
},
928 {"QueryMaxHeaderSize", cl_QueryMaxHeaderSize
},
929 {"QueryScheme", cl_QueryScheme
},
930 {"QuerySchemeFromName", cl_QuerySchemeFromName
},
931 {"SetDefault", cl_SetDefault
},
932 {"SetMax", cl_SetMax
},
933 {"SetMin", cl_SetMin
},
935 {"cvt_type", cvt_type
},
937 {NULL
, NULL
} /* Sentinel */
945 m
= initmodule("cl", cl_methods
);
946 d
= getmoduledict(m
);
948 ClError
= newstringobject("cl.error");
949 if (ClError
== NULL
|| dictinsert(d
, "error", ClError
) != 0)
950 fatal("can't define cl.error");
952 (void) clSetErrorHandler(cl_ErrorHandler
);