3 docCopyright("Steve Dekorte", 2004)
4 docLicense("BSD revised")
5 docCategory("Graphics")
6 docDescription("The Image object can read and draw images and provide the image data as a buffer. Example use;
8 image = Image clone open(\"curly.png\")
10 image scaleTo(image width / 2, image height / 2)
11 image save(\"curly.tiff\")
13 When loading an attempt will be made to convert the image into whichever of the following formats it is closest to: L8, LA8, RGB8, RGBA8.
15 Currently supported formats include PNG(which supports alpha), JPG and TIFF. ")
25 #define DATA(self) ((IoImageData *)IoObject_dataPointer(self))
27 IoTag
*IoImage_newTag(void *state
)
29 IoTag
*tag
= IoTag_newWithName_("Image");
30 IoTag_state_(tag
, state
);
31 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoImage_rawClone
);
32 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoImage_free
);
33 IoTag_markFunc_(tag
, (IoTagMarkFunc
*)IoImage_mark
);
37 IoImage
*IoImage_proto(void *state
)
39 IoObject
*self
= IoObject_new(state
);
40 IoObject_tag_(self
, IoImage_newTag(state
));
42 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoImageData
)));
44 DATA(self
)->buffer
= IoSeq_newWithCString_(IOSTATE
, "");
45 DATA(self
)->image
= Image_new();
46 Image_setExternalUArray_(DATA(self
)->image
, IoSeq_rawUArray(DATA(self
)->buffer
));
48 IoState_registerProtoWithFunc_(state
, self
, IoImage_proto
);
51 IoMethodTable methodTable
[] = {
52 {"setDataWidthHeightComponentCount", IoImage_setDataWidthHeightComponentCount
},
53 {"setPath", IoImage_setPath
},
54 {"open", IoImage_open
},
55 {"save", IoImage_save
},
57 {"width", IoImage_width
},
58 {"height", IoImage_height
},
60 {"data", IoImage_data
},
61 {"componentCount", IoImage_componentCount
},
62 {"isL8", IoImage_isL8
},
63 {"isLA8", IoImage_isLA8
},
64 {"isRGB8", IoImage_isRGB8
},
65 {"isRGBA8", IoImage_isRGBA8
},
66 {"error", IoImage_error
},
67 {"resizedTo", IoImage_resizedTo
},
68 {"crop", IoImage_crop
},
72 {"setEncodingQuality", IoImage_setEncodingQuality
},
73 {"encodingQuality", IoImage_encodingQuality
},
75 {"setDecodingWidthHint", IoImage_setDecodingWidthHint
},
76 {"decodingWidthHint", IoImage_decodingWidthHint
},
78 {"setDecodingHeightHint", IoImage_setDecodingHeightHint
},
79 {"decodingHeightHint", IoImage_decodingHeightHint
},
82 IoObject_addMethodTable_(self
, methodTable
);
87 IoImage
*IoImage_rawClone(IoImage
*proto
)
89 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
90 IoObject_setDataPointer_(self
, cpalloc(IoObject_dataPointer(proto
), sizeof(IoImageData
)));
91 DATA(self
)->buffer
= IOCLONE(DATA(proto
)->buffer
);
92 DATA(self
)->image
= Image_copyWithUArray_(DATA(proto
)->image
, IoSeq_rawUArray(DATA(self
)->buffer
));
96 IoImage
*IoImage_new(void *state
)
98 IoObject
*proto
= IoState_protoWithInitFunction_(state
, IoImage_proto
);
99 return IOCLONE(proto
);
102 /* ----------------------------------------------------------- */
104 void IoImage_free(IoImage
*self
)
106 Image_free(DATA(self
)->image
);
107 free(IoObject_dataPointer(self
));
110 void IoImage_mark(IoImage
*self
)
112 IoObject_shouldMark(DATA(self
)->buffer
);
115 Image
*IoImage_image(IoImage
*self
)
117 return DATA(self
)->image
;
120 Image
*IoImage_rawImage(IoImage
*self
)
122 return DATA(self
)->image
;
125 /* ----------------------------------------------------------- */
127 IoObject
*IoImage_path(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
131 "Returns the image path. ")
134 return IOSYMBOL(Image_path(DATA(self
)->image
));
137 IoObject
*IoImage_setPath(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
140 docSlot("setPath(aString)",
141 "Sets the image path. Returns self. ")
144 IoSymbol
*s
= IoMessage_locals_symbolArgAt_(m
, locals
, 0);
145 Image_path_(DATA(self
)->image
, CSTRING(s
));
149 void IoImage_checkError(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
151 const char *e
= Image_error(DATA(self
)->image
);
155 IoState_error_(IOSTATE
, m
, "Image %s on %s", e
, Image_path(DATA(self
)->image
));
160 IoObject
*IoImage_setDataWidthHeightComponentCount(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
163 docSlot("setDataWidthHeightComponentCount(aSequence, width, height, componentCount)",
164 "Sets the image data and it's parameters. Returns self.")
167 IoSeq
*data
= IoMessage_locals_seqArgAt_(m
, locals
, 0);
168 int w
= IoMessage_locals_intArgAt_(m
, locals
, 1);
169 int h
= IoMessage_locals_intArgAt_(m
, locals
, 2);
170 int c
= IoMessage_locals_intArgAt_(m
, locals
, 3);
172 Image_setData_width_height_componentCount_(DATA(self
)->image
, IoSeq_rawUArray(data
), w
, h
, c
);
177 IoObject
*IoImage_open(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
180 docSlot("open(optionalPathString)",
181 "Sets the path to optionalPathString if provided and opens the image file. Returns self on success, Nil on failure. ")
184 /*printf("opening Image %p %s\n", self, Image_path(DATA(self)->image));*/
186 if (IoMessage_argCount(m
) > 0)
188 IoSymbol
*path
= IoMessage_locals_symbolArgAt_(m
, locals
, 0);
189 Image_path_(DATA(self
)->image
, CSTRING(path
));
192 Image_load(DATA(self
)->image
);
193 IoImage_checkError(self
, locals
, m
);
197 IoObject
*IoImage_save(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
200 docSlot("save(optionalPathString)",
201 "Sets the path to optionalPathString if provided and saves the image in the format specified by the path extension. Returns self on success, Nil on failure. ")
204 if (IoMessage_argCount(m
) > 0)
206 IoSymbol
*path
= IoMessage_locals_symbolArgAt_(m
, locals
, 0);
207 Image_path_(DATA(self
)->image
, CSTRING(path
));
210 Image_save(DATA(self
)->image
);
211 IoImage_checkError(self
, locals
, m
);
215 IoObject
*IoImage_width(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
218 docSlot("width", "Returns the image width. ")
221 return IONUMBER(Image_width(DATA(self
)->image
));
224 IoObject
*IoImage_height(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
227 docSlot("height", "Returns the image hieght. ")
230 return IONUMBER(Image_height(DATA(self
)->image
));
233 IoObject
*IoImage_data(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
237 "Returns a Buffer primitive containing the image data(loading it first if needed). Manipulating this data will effect what is drawn when the receiver's draw method is called. ")
240 return DATA(self
)->buffer
;
243 IoObject
*IoImage_componentCount(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
245 return IONUMBER(Image_componentCount(DATA(self
)->image
));
248 IoObject
*IoImage_error(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
252 "Returns a String containing the current error or Nil if there is no error. ")
255 char *s
= (char *)Image_error(DATA(self
)->image
);
257 if ((!s
) || (!strlen(s
)))
265 IoObject
*IoImage_isRGB8(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
269 "Returns true if the receiver is in RGB8 format, false otherwise.")
272 return IOBOOL(self
, Image_componentCount(DATA(self
)->image
) == 3);
275 IoObject
*IoImage_isRGBA8(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
279 "Returns true if the receiver is in RGBA8 format, false otherwise.")
282 return IOBOOL(self
, Image_componentCount(DATA(self
)->image
) == 4);
285 IoObject
*IoImage_isL8(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
289 "Returns true if the receiver is in L8 (8bit Luminance) format, false otherwise.")
292 return IOBOOL(self
, Image_componentCount(DATA(self
)->image
) == 1);
295 IoObject
*IoImage_isLA8(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
299 "Returns true if the receiver is in LA8 (8bit Luminance-Alpha) format, false otherwise.")
302 return IOBOOL(self
, Image_componentCount(DATA(self
)->image
) == 2);
305 IoObject
*IoImage_crop(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
308 docSlot("crop(x, y, width, height)",
309 "Crops the image to the specified values. Returns self.")
312 int cx
= IoMessage_locals_intArgAt_(m
, locals
, 0);
313 int cy
= IoMessage_locals_intArgAt_(m
, locals
, 1);
314 int width
= IoMessage_locals_intArgAt_(m
, locals
, 2);
315 int height
= IoMessage_locals_intArgAt_(m
, locals
, 3);
317 Image_crop(DATA(self
)->image
, cx
, cy
, width
, height
);
318 IoImage_checkError(self
, locals
, m
);
322 IoObject
*IoImage_resizedTo(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
324 int w
= IoMessage_locals_intArgAt_(m
, locals
, 0);
325 int h
= IoMessage_locals_intArgAt_(m
, locals
, 1);
327 IoImage
*outImage
= IoImage_new(IOSTATE
);
328 Image_resizeTo(DATA(self
)->image
, w
, h
, DATA(outImage
)->image
);
329 IoImage_checkError(self
, locals
, m
);
334 /* --- extras -------------------------------------------------------- */
336 IoObject
*IoImage_setEncodingQuality(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
339 docSlot("setEncodingQuality(aNumber)",
340 "Sets the image encoding quality (range is 0.0 - 1.0, 1.0 with being the highest).")
343 Image_encodingQuality_(DATA(self
)->image
, IoMessage_locals_doubleArgAt_(m
, locals
, 0));
347 IoObject
*IoImage_encodingQuality(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
350 docSlot("encodingQuality",
351 "Returns the encodingQuality setting.")
354 return IONUMBER(Image_encodingQuality(DATA(self
)->image
));
357 IoObject
*IoImage_setDecodingWidthHint(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
361 Image_decodingWidthHint_(DATA(self
)->image
, IoMessage_locals_intArgAt_(m
, locals
, 0));
365 IoObject
*IoImage_decodingWidthHint(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
368 return IONUMBER(Image_decodingWidthHint(DATA(self
)->image
));
371 IoObject
*IoImage_setDecodingHeightHint(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
374 Image_decodingHeightHint_(DATA(self
)->image
, IoMessage_locals_intArgAt_(m
, locals
, 0));
378 IoObject
*IoImage_decodingHeightHint(IoImage
*self
, IoObject
*locals
, IoMessage
*m
)
381 return IONUMBER(Image_decodingHeightHint(DATA(self
)->image
));