Photo.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /* Photo.cpp
  2. *
  3. * Copyright (C) 2013-2018 Paul Boersma
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "Photo.h"
  19. #include "NUM2.h"
  20. #include "Formula.h"
  21. #if defined (_WIN32)
  22. #include <GraphicsP.h>
  23. #elif defined (macintosh)
  24. #include "macport_on.h"
  25. #include <Cocoa/Cocoa.h>
  26. #include "macport_off.h"
  27. #elif defined (linux) && ! defined (NO_GRAPHICS)
  28. #include <cairo/cairo.h>
  29. #endif
  30. #include "oo_DESTROY.h"
  31. #include "Photo_def.h"
  32. #include "oo_COPY.h"
  33. #include "Photo_def.h"
  34. #include "oo_EQUAL.h"
  35. #include "Photo_def.h"
  36. #include "oo_CAN_WRITE_AS_ENCODING.h"
  37. #include "Photo_def.h"
  38. #include "oo_WRITE_TEXT.h"
  39. #include "Photo_def.h"
  40. #include "oo_READ_TEXT.h"
  41. #include "Photo_def.h"
  42. #include "oo_WRITE_BINARY.h"
  43. #include "Photo_def.h"
  44. #include "oo_READ_BINARY.h"
  45. #include "Photo_def.h"
  46. #include "oo_DESCRIPTION.h"
  47. #include "Photo_def.h"
  48. Thing_implement (Photo, SampledXY, 0);
  49. void structPhoto :: v_info () {
  50. our structDaata :: v_info ();
  51. MelderInfo_writeLine (U"xmin: ", our xmin);
  52. MelderInfo_writeLine (U"xmax: ", our xmax);
  53. MelderInfo_writeLine (U"Number of columns: ", our nx);
  54. MelderInfo_writeLine (U"dx: ", our dx, U" (-> sampling rate ", 1.0 / our dx, U" )");
  55. MelderInfo_writeLine (U"x1: ", our x1);
  56. MelderInfo_writeLine (U"ymin: ", our ymin);
  57. MelderInfo_writeLine (U"ymax: ", our ymax);
  58. MelderInfo_writeLine (U"Number of rows: ", our ny);
  59. MelderInfo_writeLine (U"dy: ", our dy, U" (-> sampling rate ", 1.0 / our dy, U" )");
  60. MelderInfo_writeLine (U"y1: ", our y1);
  61. }
  62. void Photo_init (Photo me,
  63. double xmin, double xmax, integer nx, double dx, double x1,
  64. double ymin, double ymax, integer ny, double dy, double y1)
  65. {
  66. SampledXY_init (me, xmin, xmax, nx, dx, x1, ymin, ymax, ny, dy, y1);
  67. my d_red = Matrix_create (xmin, xmax, nx, dx, x1, ymin, ymax, ny, dy, y1);
  68. my d_green = Matrix_create (xmin, xmax, nx, dx, x1, ymin, ymax, ny, dy, y1);
  69. my d_blue = Matrix_create (xmin, xmax, nx, dx, x1, ymin, ymax, ny, dy, y1);
  70. my d_transparency = Matrix_create (xmin, xmax, nx, dx, x1, ymin, ymax, ny, dy, y1);
  71. }
  72. autoPhoto Photo_create
  73. (double xmin, double xmax, integer nx, double dx, double x1,
  74. double ymin, double ymax, integer ny, double dy, double y1)
  75. {
  76. try {
  77. autoPhoto me = Thing_new (Photo);
  78. Photo_init (me.get(), xmin, xmax, nx, dx, x1, ymin, ymax, ny, dy, y1);
  79. return me;
  80. } catch (MelderError) {
  81. Melder_throw (U"Photo object not created.");
  82. }
  83. }
  84. autoPhoto Photo_createSimple (integer numberOfRows, integer numberOfColumns) {
  85. try {
  86. autoPhoto me = Thing_new (Photo);
  87. Photo_init (me.get(), 0.5, numberOfColumns + 0.5, numberOfColumns, 1, 1,
  88. 0.5, numberOfRows + 0.5, numberOfRows, 1, 1);
  89. return me;
  90. } catch (MelderError) {
  91. Melder_throw (U"Photo object not created.");
  92. }
  93. }
  94. autoPhoto Photo_readFromImageFile (MelderFile file) {
  95. try {
  96. #if defined (linux) && ! defined (NO_GRAPHICS)
  97. cairo_surface_t *surface = cairo_image_surface_create_from_png (Melder_peek32to8 (file -> path));
  98. //if (cairo_surface_status)
  99. // Melder_throw (U"Error opening PNG file.");
  100. integer width = cairo_image_surface_get_width (surface);
  101. integer height = cairo_image_surface_get_height (surface);
  102. if (width == 0 || height == 0) {
  103. cairo_surface_destroy (surface);
  104. Melder_throw (U"Error reading PNG file.");
  105. }
  106. uint8 *imageData = cairo_image_surface_get_data (surface);
  107. integer bytesPerRow = cairo_image_surface_get_stride (surface);
  108. cairo_format_t format = cairo_image_surface_get_format (surface);
  109. autoPhoto me = Photo_createSimple (height, width);
  110. if (format == CAIRO_FORMAT_ARGB32) {
  111. for (integer irow = 1; irow <= height; irow ++) {
  112. uint8 *rowAddress = imageData + bytesPerRow * (height - irow);
  113. for (integer icol = 1; icol <= width; icol ++) {
  114. my d_blue -> z [irow] [icol] = (* rowAddress ++) / 255.0;
  115. my d_green -> z [irow] [icol] = (* rowAddress ++) / 255.0;
  116. my d_red -> z [irow] [icol] = (* rowAddress ++) / 255.0;
  117. my d_transparency -> z [irow] [icol] = 1.0 - (* rowAddress ++) / 255.0;
  118. }
  119. }
  120. } else if (format == CAIRO_FORMAT_RGB24) {
  121. for (integer irow = 1; irow <= height; irow ++) {
  122. uint8 *rowAddress = imageData + bytesPerRow * (height - irow);
  123. for (integer icol = 1; icol <= width; icol ++) {
  124. my d_blue -> z [irow] [icol] = (* rowAddress ++) / 255.0;
  125. my d_green -> z [irow] [icol] = (* rowAddress ++) / 255.0;
  126. my d_red -> z [irow] [icol] = (* rowAddress ++) / 255.0;
  127. my d_transparency -> z [irow] [icol] = 0.0; rowAddress ++;
  128. }
  129. }
  130. } else {
  131. cairo_surface_destroy (surface);
  132. Melder_throw (U"Unsupported PNG format ", format, U".");
  133. }
  134. cairo_surface_destroy (surface);
  135. return me;
  136. #elif defined (_WIN32)
  137. Gdiplus::Bitmap gdiplusBitmap (Melder_peek32toW (file -> path));
  138. integer width = gdiplusBitmap. GetWidth ();
  139. integer height = gdiplusBitmap. GetHeight ();
  140. if (width == 0 || height == 0)
  141. Melder_throw (U"Error reading PNG file.");
  142. autoPhoto me = Photo_createSimple (height, width);
  143. for (integer irow = 1; irow <= height; irow ++) {
  144. for (integer icol = 1; icol <= width; icol ++) {
  145. Gdiplus::Color gdiplusColour;
  146. gdiplusBitmap. GetPixel (icol - 1, height - irow, & gdiplusColour);
  147. my d_red -> z [irow] [icol] = (gdiplusColour. GetRed ()) / 255.0;
  148. my d_green -> z [irow] [icol] = (gdiplusColour. GetGreen ()) / 255.0;
  149. my d_blue -> z [irow] [icol] = (gdiplusColour. GetBlue ()) / 255.0;
  150. my d_transparency -> z [irow] [icol] = 1.0 - (gdiplusColour. GetAlpha ()) / 255.0;
  151. }
  152. }
  153. return me;
  154. #elif defined (macintosh)
  155. autoPhoto me;
  156. char utf8 [500];
  157. Melder_str32To8bitFileRepresentation_inplace (file -> path, utf8);
  158. CFStringRef path = CFStringCreateWithCString (nullptr, utf8, kCFStringEncodingUTF8);
  159. CFURLRef url = CFURLCreateWithFileSystemPath (nullptr, path, kCFURLPOSIXPathStyle, false);
  160. CFRelease (path);
  161. CGImageSourceRef imageSource = CGImageSourceCreateWithURL (url, nullptr);
  162. CFRelease (url);
  163. if (! imageSource)
  164. Melder_throw (U"Cannot open picture file ", file, U".");
  165. CGImageRef image = CGImageSourceCreateImageAtIndex (imageSource, 0, nullptr);
  166. CFRelease (imageSource);
  167. if (image) {
  168. integer width = CGImageGetWidth (image);
  169. integer height = CGImageGetHeight (image);
  170. me = Photo_createSimple (height, width);
  171. integer bitsPerPixel = CGImageGetBitsPerPixel (image);
  172. integer bitsPerComponent = CGImageGetBitsPerComponent (image);
  173. integer bytesPerRow = CGImageGetBytesPerRow (image);
  174. trace (
  175. bitsPerPixel, U" bits per pixel, ",
  176. bitsPerComponent, U" bits per component, ",
  177. bytesPerRow, U" bytes per row"
  178. );
  179. /*
  180. * Now we probably need to use:
  181. * CGColorSpaceRef CGImageGetColorSpace (CGImageRef image);
  182. * CGImageAlphaInfo CGImageGetAlphaInfo (CGImageRef image);
  183. */
  184. CGDataProviderRef dataProvider = CGImageGetDataProvider (image); // not retained, so don't release
  185. CFDataRef data = CGDataProviderCopyData (dataProvider);
  186. uint8 *pixelData = (uint8_t *) CFDataGetBytePtr (data);
  187. for (integer irow = 1; irow <= height; irow ++) {
  188. uint8 *rowAddress = pixelData + bytesPerRow * (height - irow);
  189. for (integer icol = 1; icol <= width; icol ++) {
  190. my d_red -> z [irow] [icol] = (*rowAddress ++) / 255.0;
  191. my d_green -> z [irow] [icol] = (*rowAddress ++) / 255.0;
  192. my d_blue -> z [irow] [icol] = (*rowAddress ++) / 255.0;
  193. my d_transparency -> z [irow] [icol] = 1.0 - (*rowAddress ++) / 255.0;
  194. }
  195. }
  196. CFRelease (data);
  197. CGImageRelease (image);
  198. }
  199. return me;
  200. #else
  201. return autoPhoto();
  202. #endif
  203. } catch (MelderError) {
  204. Melder_throw (U"Picture file ", file, U" not opened as Photo.");
  205. }
  206. }
  207. #if defined (macintosh)
  208. #include <time.h>
  209. #include "macport_on.h"
  210. static void _mac_releaseDataCallback (void * /* info */, const void *data, size_t /* size */) {
  211. Melder_free (data);
  212. }
  213. #endif
  214. #if defined (linux) && ! defined (NO_GRAPHICS)
  215. static void _lin_saveAsImageFile (Photo me, MelderFile file, conststring32 which) {
  216. cairo_format_t format = CAIRO_FORMAT_ARGB32;
  217. integer bytesPerRow = cairo_format_stride_for_width (format, my nx); // likely to be my nx * 4
  218. integer numberOfRows = my ny;
  219. uint8 *imageData = Melder_malloc_f (uint8, bytesPerRow * numberOfRows);
  220. for (integer irow = 1; irow <= my ny; irow ++) {
  221. uint8 *rowAddress = imageData + bytesPerRow * (my ny - irow);
  222. for (integer icol = 1; icol <= my nx; icol ++) {
  223. * rowAddress ++ = Melder_iround (my d_blue -> z [irow] [icol] * 255.0);
  224. * rowAddress ++ = Melder_iround (my d_green -> z [irow] [icol] * 255.0);
  225. * rowAddress ++ = Melder_iround (my d_red -> z [irow] [icol] * 255.0);
  226. * rowAddress ++ = 255 - Melder_iround (my d_transparency -> z [irow] [icol] * 255.0);
  227. }
  228. }
  229. cairo_surface_t *surface = cairo_image_surface_create_for_data (imageData,
  230. format, my nx, my ny, bytesPerRow);
  231. cairo_surface_write_to_png (surface, Melder_peek32to8 (file -> path));
  232. cairo_surface_destroy (surface);
  233. }
  234. #endif
  235. #ifdef _WIN32
  236. static void _win_saveAsImageFile (Photo me, MelderFile file, conststring32 mimeType) {
  237. Gdiplus::Bitmap gdiplusBitmap (my nx, my ny, PixelFormat32bppARGB);
  238. for (integer irow = 1; irow <= my ny; irow ++) {
  239. for (integer icol = 1; icol <= my nx; icol ++) {
  240. Gdiplus::Color gdiplusColour (
  241. 255 - Melder_iround (my d_transparency -> z [irow] [icol] * 255.0),
  242. Melder_iround (my d_red -> z [irow] [icol] * 255.0),
  243. Melder_iround (my d_green -> z [irow] [icol] * 255.0),
  244. Melder_iround (my d_blue -> z [irow] [icol] * 255.0));
  245. gdiplusBitmap. SetPixel (icol - 1, my ny - irow, gdiplusColour);
  246. }
  247. }
  248. /*
  249. * The 'mimeType' parameter specifies a "class encoder". Look it up.
  250. */
  251. UINT numberOfImageEncoders, sizeOfImageEncoderArray;
  252. Gdiplus::GetImageEncodersSize (& numberOfImageEncoders, & sizeOfImageEncoderArray);
  253. if (sizeOfImageEncoderArray == 0)
  254. Melder_throw (U"Cannot find image encoders.");
  255. Gdiplus::ImageCodecInfo *imageEncoderInfos = Melder_malloc (Gdiplus::ImageCodecInfo, sizeOfImageEncoderArray);
  256. Gdiplus::GetImageEncoders (numberOfImageEncoders, sizeOfImageEncoderArray, imageEncoderInfos);
  257. for (int iencoder = 0; iencoder < numberOfImageEncoders; iencoder ++) {
  258. trace (U"Supported MIME type: ", Melder_peekWto32 (imageEncoderInfos [iencoder]. MimeType));
  259. if (str32equ (Melder_peekWto32 (imageEncoderInfos [iencoder]. MimeType), mimeType)) {
  260. Gdiplus::EncoderParameters *p = nullptr;
  261. Gdiplus::EncoderParameters encoderParameters;
  262. if (str32equ (mimeType, U"image/jpeg")) {
  263. encoderParameters. Count = 1;
  264. GUID guid = { 0x1D5B'E4B5, 0xFA4A, 0x452D, { 0x9C, 0xDD, 0x5D, 0xB3, 0x51, 0x05, 0xE7, 0xEB }}; // EncoderQuality
  265. encoderParameters. Parameter [0]. Guid = guid;
  266. encoderParameters. Parameter [0]. Type = Gdiplus::EncoderParameterValueTypeLong;
  267. encoderParameters. Parameter [0]. NumberOfValues = 1;
  268. ULONG quality = 100;
  269. encoderParameters. Parameter [0]. Value = & quality;
  270. p = & encoderParameters;
  271. }
  272. gdiplusBitmap. Save (Melder_peek32toW (file -> path), & imageEncoderInfos [iencoder]. Clsid, p);
  273. Melder_free (imageEncoderInfos);
  274. return;
  275. }
  276. }
  277. Melder_throw (U"Unknown MIME type ", mimeType, U".");
  278. }
  279. #endif
  280. #ifdef macintosh
  281. static void _mac_saveAsImageFile (Photo me, MelderFile file, const void *which) {
  282. integer bytesPerRow = my nx * 4;
  283. integer numberOfRows = my ny;
  284. unsigned char *imageData = Melder_malloc_f (unsigned char, bytesPerRow * numberOfRows);
  285. for (integer irow = 1; irow <= my ny; irow ++) {
  286. uint8 *rowAddress = imageData + bytesPerRow * (my ny - irow);
  287. for (integer icol = 1; icol <= my nx; icol ++) {
  288. * rowAddress ++ = (uint8) Melder_iround (my d_red -> z [irow] [icol] * 255.0); // BUG: should be tested for speed
  289. * rowAddress ++ = (uint8) Melder_iround (my d_green -> z [irow] [icol] * 255.0);
  290. * rowAddress ++ = (uint8) Melder_iround (my d_blue -> z [irow] [icol] * 255.0);
  291. * rowAddress ++ = 255 - (uint8) Melder_iround (my d_transparency -> z [irow] [icol] * 255.0);
  292. }
  293. }
  294. static CGColorSpaceRef colourSpace = nullptr;
  295. if (! colourSpace) {
  296. colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB); // used to be kCGColorSpaceUserRGB
  297. Melder_assert (colourSpace);
  298. }
  299. CGDataProviderRef dataProvider = CGDataProviderCreateWithData (nullptr,
  300. imageData,
  301. bytesPerRow * numberOfRows,
  302. _mac_releaseDataCallback // needed?
  303. );
  304. Melder_assert (dataProvider);
  305. CGImageRef image = CGImageCreate (my nx, numberOfRows,
  306. 8, 32, bytesPerRow, colourSpace, kCGImageAlphaNone, dataProvider, nullptr, false, kCGRenderingIntentDefault);
  307. CGDataProviderRelease (dataProvider);
  308. Melder_assert (image);
  309. NSString *path = (NSString *) Melder_peek32toCfstring (Melder_fileToPath (file));
  310. CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: path isDirectory: NO];
  311. CGImageDestinationRef destination = CGImageDestinationCreateWithURL (url, (CFStringRef) which, 1, nullptr);
  312. CGImageDestinationAddImage (destination, image, nil);
  313. if (! CGImageDestinationFinalize (destination)) {
  314. //Melder_throw;
  315. }
  316. CFRelease (destination);
  317. CGColorSpaceRelease (colourSpace);
  318. CGImageRelease (image);
  319. }
  320. #endif
  321. void Photo_saveAsPNG (Photo me, MelderFile file) {
  322. #if defined (_WIN32)
  323. _win_saveAsImageFile (me, file, U"image/png");
  324. #elif defined (macintosh)
  325. _mac_saveAsImageFile (me, file, kUTTypePNG);
  326. #elif defined (linux) && ! defined (NO_GRAPHICS)
  327. _lin_saveAsImageFile (me, file, U"image/png");
  328. #endif
  329. }
  330. void Photo_saveAsTIFF (Photo me, MelderFile file) {
  331. #if defined (_WIN32)
  332. _win_saveAsImageFile (me, file, U"image/tiff");
  333. #elif defined (macintosh)
  334. _mac_saveAsImageFile (me, file, kUTTypeTIFF);
  335. #else
  336. (void) me;
  337. (void) file;
  338. #endif
  339. }
  340. void Photo_saveAsGIF (Photo me, MelderFile file) {
  341. #if defined (_WIN32)
  342. _win_saveAsImageFile (me, file, U"image/gif");
  343. #elif defined (macintosh)
  344. _mac_saveAsImageFile (me, file, kUTTypeGIF);
  345. #else
  346. (void) me;
  347. (void) file;
  348. #endif
  349. }
  350. void Photo_saveAsWindowsBitmapFile (Photo me, MelderFile file) {
  351. #if defined (_WIN32)
  352. _win_saveAsImageFile (me, file, U"image/bmp");
  353. #elif defined (macintosh)
  354. _mac_saveAsImageFile (me, file, kUTTypeBMP);
  355. #else
  356. (void) me;
  357. (void) file;
  358. #endif
  359. }
  360. void Photo_saveAsJPEG (Photo me, MelderFile file) {
  361. #if defined (_WIN32)
  362. _win_saveAsImageFile (me, file, U"image/jpeg");
  363. #elif defined (macintosh)
  364. _mac_saveAsImageFile (me, file, kUTTypeJPEG);
  365. #else
  366. (void) me;
  367. (void) file;
  368. #endif
  369. }
  370. void Photo_saveAsJPEG2000 (Photo me, MelderFile file) {
  371. #if defined (_WIN32)
  372. _win_saveAsImageFile (me, file, U"image/jpeg2000");
  373. #elif defined (macintosh)
  374. _mac_saveAsImageFile (me, file, kUTTypeJPEG2000);
  375. #else
  376. (void) me;
  377. (void) file;
  378. #endif
  379. }
  380. void Photo_saveAsAppleIconFile (Photo me, MelderFile file) {
  381. #if defined (_WIN32)
  382. _win_saveAsImageFile (me, file, U"image/ICNS");
  383. #elif defined (macintosh)
  384. _mac_saveAsImageFile (me, file, kUTTypeAppleICNS);
  385. #else
  386. (void) me;
  387. (void) file;
  388. #endif
  389. }
  390. void Photo_saveAsWindowsIconFile (Photo me, MelderFile file) {
  391. #if defined (_WIN32)
  392. _win_saveAsImageFile (me, file, U"image/icon");
  393. #elif defined (macintosh)
  394. _mac_saveAsImageFile (me, file, kUTTypeICO);
  395. #else
  396. (void) me;
  397. (void) file;
  398. #endif
  399. }
  400. void Photo_replaceRed (Photo me, Matrix red) {
  401. my d_red = Data_copy (red);
  402. }
  403. void Photo_replaceGreen (Photo me, Matrix green) {
  404. my d_green = Data_copy (green);
  405. }
  406. void Photo_replaceBlue (Photo me, Matrix blue) {
  407. my d_blue = Data_copy (blue);
  408. }
  409. void Photo_replaceTransparency (Photo me, Matrix transparency) {
  410. my d_transparency = Data_copy (transparency);
  411. }
  412. static void _Photo_cellArrayOrImage (Photo me, Graphics g, double xmin, double xmax, double ymin, double ymax, bool interpolate) {
  413. if (xmax <= xmin) { xmin = my xmin; xmax = my xmax; }
  414. if (ymax <= ymin) { ymin = my ymin; ymax = my ymax; }
  415. integer ixmin, ixmax, iymin, iymax;
  416. Sampled_getWindowSamples (me, xmin - 0.49999 * my dx, xmax + 0.49999 * my dx, & ixmin, & ixmax);
  417. SampledXY_getWindowSamplesY (me, ymin - 0.49999 * my dy, ymax + 0.49999 * my dy, & iymin, & iymax);
  418. if (ixmin > ixmax || iymin > iymax) {
  419. Melder_fatal (U"ixmin ", ixmin, U" ixmax ", ixmax, U" iymin ", iymin, U" iymax ", iymax);
  420. return;
  421. }
  422. Graphics_setInner (g);
  423. Graphics_setWindow (g, xmin, xmax, ymin, ymax);
  424. autoNUMmatrix <double_rgbt> z (iymin, iymax, ixmin, ixmax);
  425. for (integer iy = iymin; iy <= iymax; iy ++) {
  426. for (integer ix = ixmin; ix <= ixmax; ix ++) {
  427. z [iy] [ix]. red = my d_red -> z [iy] [ix];
  428. z [iy] [ix]. green = my d_green -> z [iy] [ix];
  429. z [iy] [ix]. blue = my d_blue -> z [iy] [ix];
  430. z [iy] [ix]. transparency = my d_transparency -> z [iy] [ix];
  431. }
  432. }
  433. if (interpolate)
  434. Graphics_image_colour (g, z.peek(),
  435. ixmin, ixmax, Sampled_indexToX (me, ixmin - 0.5), Sampled_indexToX (me, ixmax + 0.5),
  436. iymin, iymax, SampledXY_indexToY (me, iymin - 0.5), SampledXY_indexToY (me, iymax + 0.5), 0.0, 1.0);
  437. else
  438. Graphics_cellArray_colour (g, z.peek(),
  439. ixmin, ixmax, Sampled_indexToX (me, ixmin - 0.5), Sampled_indexToX (me, ixmax + 0.5),
  440. iymin, iymax, SampledXY_indexToY (me, iymin - 0.5), SampledXY_indexToY (me, iymax + 0.5), 0.0, 1.0);
  441. //Graphics_rectangle (g, xmin, xmax, ymin, ymax);
  442. Graphics_unsetInner (g);
  443. }
  444. void Photo_paintImage (Photo me, Graphics g, double xmin, double xmax, double ymin, double ymax) {
  445. _Photo_cellArrayOrImage (me, g, xmin, xmax, ymin, ymax, true);
  446. }
  447. void Photo_paintCells (Photo me, Graphics g, double xmin, double xmax, double ymin, double ymax) {
  448. _Photo_cellArrayOrImage (me, g, xmin, xmax, ymin, ymax, false);
  449. }
  450. /* End of file Photo.cpp */