Guest User

Untitled

a guest
Jul 19th, 2018
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.66 KB | None | 0 0
  1. /**
  2. * lzw.h
  3. * Function declarations for lempel ziv-welch decompression algorithm.
  4. */
  5.  
  6. #ifndef LZW_H
  7. #define LZW_H
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11.  
  12. /**
  13. * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
  14. */
  15. void free_dict (unsigned char* dict[], int from, int to);
  16.  
  17. /**
  18. * Enters the first 256 ASCII values into dict.
  19. */
  20. void load_dict_defaults (unsigned char* dict[]);
  21.  
  22. /**
  23. * Reads 12 bits from source and returns them as an int.
  24. */
  25. int fread_twelve(FILE* source);
  26.  
  27. /**
  28. * LZW decompression of source to dest.
  29. * Returns 0 if successful, a positive integer otherwise.
  30. */
  31. int decompress (FILE* source, FILE* dest);
  32.  
  33. #endif // LZW_H
  34.  
  35. /**
  36. * decompress.c
  37. * Implementation of lempel ziv-welch decompression algorithm using 12-bit fixed-width compression format.
  38. *
  39. * Usage: decompress
  40. */
  41.  
  42. #include "lzw.h"
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45.  
  46. int main (int argc, char* argv[])
  47. {
  48. // check for correct number of args
  49. if (argc != 3)
  50. {
  51. printf("Usage: decompress source destinationn");
  52. return 1;
  53. }
  54.  
  55. // open compressed file
  56. FILE* source = fopen(argv[1], "r");
  57. if (source == NULL)
  58. {
  59. printf("Error: cannot open %sn", argv[1]);
  60. return 1;
  61. }
  62.  
  63. // open destination file
  64. FILE* dest = fopen(argv[2], "w");
  65. if (dest == NULL)
  66. {
  67. printf("Error: cannot open %sn", argv[2]);
  68. return 1;
  69. }
  70.  
  71. // decompress
  72. if (decompress(source, dest) == 1)
  73. {
  74. printf("Decompression failedn");
  75. fclose(source);
  76. fclose(dest);
  77. return 1;
  78. }
  79. else
  80. {
  81. fclose(source);
  82. fclose(dest);
  83. return 0;
  84. }
  85. }
  86.  
  87. /**
  88. * lzw.c
  89. * Implementation of lempel ziv-welch decompression algorithm using 12-bit fixed-width compression format.
  90. *
  91. */
  92.  
  93. #include "lzw.h"
  94. #include <stdio.h>
  95. #include <stdlib.h>
  96. #include <string.h>
  97. #include <stdbool.h>
  98.  
  99. unsigned char* dictionary[4096];
  100.  
  101. /**
  102. * Enters the first 256 ASCII values into dict.
  103. */
  104. void load_dict_defaults (unsigned char* dict[])
  105. {
  106. unsigned char* temp;
  107. unsigned char c = 0;
  108. for (int i = 0; i < 256; i++)
  109. {
  110. temp = calloc(2, sizeof(unsigned char));
  111. temp[0] = c++;
  112. dict[i] = temp;
  113. }
  114. }
  115.  
  116. /**
  117. * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
  118. */
  119. void free_dict (unsigned char* dict[], int from, int to)
  120. {
  121. for (int i = from; i <= to; i++)
  122. {
  123. free(dict[i]);
  124. }
  125. }
  126.  
  127. /**
  128. * Reads 12 bits from source and returns them as an int.
  129. * Returns 0 on an error or EOF.
  130. */
  131. int fread_twelve(FILE* source)
  132. {
  133. int value;
  134. static bool left = true;
  135.  
  136. unsigned char buf[2];
  137.  
  138. if (left)
  139. {
  140. // if left, read two bytes and calculate int
  141. if (fread(buf, 1, 2, source) != 2) {return 0;}
  142.  
  143. if (feof(source)) // we're at a 16-bit end!
  144. {
  145. value = (buf[0] << 8) | buf[1];
  146. }
  147. else
  148. {
  149. value = (buf[0] << 4) | (buf[1] >> 4);
  150. }
  151. left = false;
  152. }
  153. else
  154. {
  155. // if right, rewind source by one byte, read two bytes and calculate int
  156. fseek(source, -1, SEEK_CUR);
  157. if (fread(buf, 1, 2, source) != 2) {return 0;}
  158. value = ((buf[0] & 0x0F) << 8) | buf[1];
  159. left = true;
  160. }
  161. return value;
  162. }
  163.  
  164. /**
  165. * LZW decompression of source to dest.
  166. * Returns 0 if successful, a positive integer otherwise.
  167. */
  168. int decompress (FILE* source, FILE* dest)
  169. {
  170. load_dict_defaults(dictionary);
  171.  
  172. int dictPos = 256;
  173.  
  174. int prevCode, currCode;
  175. unsigned char* prevString, *currString;
  176.  
  177. // read in the first character
  178. currCode = fread_twelve(source);
  179. if (dictionary[currCode] == NULL)
  180. {
  181. return 1;
  182. }
  183. size_t size;
  184. size = strlen((char*)dictionary[currCode]);
  185. currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
  186. if (currString == NULL)
  187. {
  188. return 1;
  189. }
  190. memcpy(currString, dictionary[currCode], size+1);
  191. fprintf(dest, "%s", currString);
  192. prevCode = currCode;
  193. prevString = currString;
  194.  
  195. // read in the rest of the characters
  196. while ( (currCode = fread_twelve(source)) && currCode )
  197. {
  198. if (dictionary[currCode] == NULL)
  199. {
  200. return 1;
  201. }
  202. size = strlen((char*)dictionary[currCode]);
  203. currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
  204. if (currString == NULL)
  205. {
  206. return 1;
  207. }
  208. memcpy(currString, dictionary[currCode], size+1);
  209. fprintf(dest, "%s", currString);
  210.  
  211. if (currCode > dictPos)
  212. {
  213. dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)prevString, 1);
  214. }
  215. else
  216. {
  217. dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)currString, 1);
  218. }
  219.  
  220. // restart dict if full.
  221. if (dictPos >= 4096)
  222. {
  223. free_dict(dictionary, 256, 4096);
  224. dictPos = 256;
  225. }
  226.  
  227. prevCode = currCode;
  228. prevString = currString;
  229. }
  230.  
  231. free_dict(dictionary, 0, dictPos-1);
  232.  
  233. return 0;
  234. }
  235.  
  236. fprintf(dest, "%s", currString);
  237.  
  238. while ( (currCode = fread_twelve(source)) && currCode )
  239. {
  240. if (dictionary[currCode] == NULL)
  241. {
  242. return 1;
  243. }
  244.  
  245. if (dictionary[currCode] == NULL)
  246.  
  247. currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
  248. currString = calloc((strlen((char*)dictionary[currCode]) + 2), sizeof(char));
  249.  
  250. static bool left = true;
  251. static unsigned char prevByte = 0;
  252.  
  253. if (left)
  254. {
  255. // ...
  256. prevByte = buf[1];
  257. }
  258. else
  259. {
  260. if (fread(buf, 1, 1, source) != 1) {return 0;}
  261. value = ((prevByte & 0x0F) << 8) | buf[0];
  262. left = true;
  263. }
Add Comment
Please, Sign In to add comment