pa03.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Do not modify this file.
  3. */
  4. #include "pa03.h"
  5. #include <assert.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. static void showUsage()
  10. {
  11. printf("\n"
  12. " Usage: pa03 <image-file-1> <image-file-2> <output-filename>\n"
  13. "\n"
  14. " (1) Loades image-file-1 and image-file-2\n"
  15. " (2) Convolves 2 with 1\n"
  16. " (3) Draws a bounding box around the convolution peak\n"
  17. " (4) Saves the result to \"output-filename\" in PPM format\n"
  18. "\n");
  19. }
  20. static void setPixel(uint8_t* pixels, int width, int height, int x, int y, int c, uint8_t value)
  21. {
  22. if(x < 0 || y < 0 || c < 0 || x >= width || y >= width || c >= 3)
  23. return; // index out of bounds
  24. int idx = (x + y * width)*3 + c; // three bytes per pixel. i.e., RGB
  25. pixels[idx] = value;
  26. }
  27. static int processResult(struct Image* image, struct Point peak, int width, int height, const char* filename)
  28. {
  29. // Save the image in "ppm" format
  30. int result = 0; // i.e., failure
  31. // Firstly, we want to draw a bounding box around 'peak', in the read channel.
  32. // We'll need to convert the image data to RGB...
  33. uint8_t* pixels = (uint8_t*) malloc(image->width * image->height * 3);
  34. if(!pixels)
  35. return 0; // i.e., faiture to allocate memory
  36. const int im_size = image->width * image->height;
  37. const uint8_t* im_data = image->data;
  38. const uint8_t* end = image->data + im_size;
  39. uint8_t* itr = pixels;
  40. for( ; im_data < end; ++im_data) {
  41. *itr++ = *im_data; // R
  42. *itr++ = *im_data; // G
  43. *itr++ = *im_data; // B
  44. }
  45. // Now draw the red box
  46. int x, y;
  47. int pad = 3;
  48. for(x = peak.x - pad; x <= peak.x + width + pad; ++x) {
  49. setPixel(pixels, image->width, image->height, x, peak.y - pad, 0, 0xff);
  50. setPixel(pixels, image->width, image->height, x, peak.y + height + pad, 0, 0xff);
  51. }
  52. for(y = peak.y - pad; y <= peak.y + height + pad; ++y) {
  53. setPixel(pixels, image->width, image->height, peak.x - pad, y, 0, 0xff);
  54. setPixel(pixels, image->width, image->height, peak.x + width + pad, y, 0, 0xff);
  55. }
  56. // Now write the image in PPM format. You can read PPM with "gimp" of "feh"
  57. FILE* fp = fopen(filename, "wb");
  58. if(fp) {
  59. fprintf(fp, "P6\n# %s\n%d %d 255\n", image->comment, image->width, image->height);
  60. fwrite(pixels, image->width * image->height * 3, 1, fp);
  61. fclose(fp);
  62. result = 1; // i.e, success
  63. }
  64. free(pixels);
  65. return result;
  66. }
  67. int main(int argc, char * * argv)
  68. {
  69. int result = EXIT_SUCCESS;
  70. struct Image* image1 = NULL;
  71. struct Image* image2 = NULL;
  72. // parse command-line arguments
  73. if(argc != 4) {
  74. showUsage();
  75. } else {
  76. image1 = loadImage(argv[1]);
  77. if(!image1) {
  78. fprintf(stderr, "Failed to load image file '%s'\n", argv[1]);
  79. result = EXIT_FAILURE;
  80. }
  81. image2 = loadImage(argv[2]);
  82. if(!image2) {
  83. fprintf(stderr, "Failed to load image file '%s'\n", argv[2]);
  84. result = EXIT_FAILURE;
  85. }
  86. if(image1 && image2) {
  87. struct Point peak = convolutionMax(image1, image2);
  88. if(!processResult(image1, peak, image2->width, image2->height, argv[3]))
  89. result = EXIT_FAILURE;
  90. }
  91. }
  92. freeImage(image1);
  93. freeImage(image2);
  94. return result;
  95. }