1 /* Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved. 2 3 This software is provided AS-IS with no warranty, either express or 4 implied. 5 6 This software is distributed under license and may not be copied, 7 modified or distributed except as expressly authorized under the terms 8 of the license contained in the file LICENSE in this distribution. 9 10 For more information about licensing, please refer to 11 http://www.ghostscript.com/licensing/. For information on 12 commercial licensing, go to http://www.artifex.com/licensing/ or 13 contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14 San Rafael, CA 94903, U.S.A., +1(415)492-9861. 15 */ 16 17 /* $Id: gdevtfnx.c,v 1.7 2002/02/21 22:24:52 giles Exp $ */ 18 /* 12-bit & 24-bit RGB uncompressed TIFF driver */ 19 #include "gdevprn.h" 20 #include "gdevtifs.h" 21 22 /* 23 * Thanks to Alan Barclay <alan@escribe.co.uk> for donating the original 24 * version of this code to Ghostscript. 25 */ 26 27 /* ------ The device descriptors ------ */ 28 29 /* Default X and Y resolution */ 30 #define X_DPI 72 31 #define Y_DPI 72 32 33 typedef struct gx_device_tiff_s { 34 gx_device_common; 35 gx_prn_device_common; 36 gdev_tiff_state tiff; 37 } gx_device_tiff; 38 39 private dev_proc_print_page(tiff12_print_page); 40 private dev_proc_print_page(tiff24_print_page); 41 42 private const gx_device_procs tiff12_procs = 43 prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close, 44 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb); 45 private const gx_device_procs tiff24_procs = 46 prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close, 47 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb); 48 49 const gx_device_printer gs_tiff12nc_device = { 50 prn_device_std_body(gx_device_tiff, tiff12_procs, "tiff12nc", 51 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 52 X_DPI, Y_DPI, 53 0, 0, 0, 0, 54 24, tiff12_print_page) 55 }; 56 57 const gx_device_printer gs_tiff24nc_device = { 58 prn_device_std_body(gx_device_tiff, tiff24_procs, "tiff24nc", 59 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 60 X_DPI, Y_DPI, 61 0, 0, 0, 0, 62 24, tiff24_print_page) 63 }; 64 65 /* ------ Private definitions ------ */ 66 67 /* Define our TIFF directory - sorted by tag number */ 68 typedef struct tiff_rgb_directory_s { 69 TIFF_dir_entry BitsPerSample; 70 TIFF_dir_entry Compression; 71 TIFF_dir_entry Photometric; 72 TIFF_dir_entry FillOrder; 73 TIFF_dir_entry SamplesPerPixel; 74 } tiff_rgb_directory; 75 typedef struct tiff_rgb_values_s { 76 TIFF_ushort bps[3]; 77 } tiff_rgb_values; 78 79 private const tiff_rgb_directory dir_rgb_template = 80 { 81 /* C's ridiculous rules about & and arrays require bps[0] here: */ 82 {TIFFTAG_BitsPerSample, TIFF_SHORT | TIFF_INDIRECT, 3, offset_of(tiff_rgb_values, bps[0])}, 83 {TIFFTAG_Compression, TIFF_SHORT, 1, Compression_none}, 84 {TIFFTAG_Photometric, TIFF_SHORT, 1, Photometric_RGB}, 85 {TIFFTAG_FillOrder, TIFF_SHORT, 1, FillOrder_MSB2LSB}, 86 {TIFFTAG_SamplesPerPixel, TIFF_SHORT, 1, 3}, 87 }; 88 89 private const tiff_rgb_values val_12_template = { 90 {4, 4, 4} 91 }; 92 93 private const tiff_rgb_values val_24_template = { 94 {8, 8, 8} 95 }; 96 97 /* ------ Private functions ------ */ 98 99 private int 100 tiff12_print_page(gx_device_printer * pdev, FILE * file) 101 { 102 gx_device_tiff *const tfdev = (gx_device_tiff *)pdev; 103 int code; 104 105 /* Write the page directory. */ 106 code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file, 107 (const TIFF_dir_entry *)&dir_rgb_template, 108 sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry), 109 (const byte *)&val_12_template, 110 sizeof(val_12_template), 0); 111 if (code < 0) 112 return code; 113 114 /* Write the page data. */ 115 { 116 int y; 117 int raster = gdev_prn_raster(pdev); 118 byte *line = gs_alloc_bytes(pdev->memory, raster, "tiff12_print_page"); 119 byte *row; 120 121 if (line == 0) 122 return_error(gs_error_VMerror); 123 124 for (y = 0; y < pdev->height; ++y) { 125 const byte *src; 126 byte *dest; 127 int x; 128 129 code = gdev_prn_get_bits(pdev, y, line, &row); 130 if (code < 0) 131 break; 132 133 for (src = row, dest = line, x = 0; x < raster; 134 src += 6, dest += 3, x += 6 135 ) { 136 dest[0] = (src[0] & 0xf0) | (src[1] >> 4); 137 dest[1] = (src[2] & 0xf0) | (src[3] >> 4); 138 dest[2] = (src[4] & 0xf0) | (src[5] >> 4); 139 } 140 fwrite(line, 1, (pdev->width * 3 + 1) >> 1, file); 141 } 142 143 gdev_tiff_end_strip(&tfdev->tiff, file); 144 gdev_tiff_end_page(&tfdev->tiff, file); 145 gs_free_object(pdev->memory, line, "tiff12_print_page"); 146 } 147 148 return code; 149 } 150 151 private int 152 tiff24_print_page(gx_device_printer * pdev, FILE * file) 153 { 154 gx_device_tiff *const tfdev = (gx_device_tiff *)pdev; 155 int code; 156 157 /* Write the page directory. */ 158 code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file, 159 (const TIFF_dir_entry *)&dir_rgb_template, 160 sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry), 161 (const byte *)&val_24_template, 162 sizeof(val_24_template), 0); 163 if (code < 0) 164 return code; 165 166 /* Write the page data. */ 167 { 168 int y; 169 int raster = gdev_prn_raster(pdev); 170 byte *line = gs_alloc_bytes(pdev->memory, raster, "tiff24_print_page"); 171 byte *row; 172 173 if (line == 0) 174 return_error(gs_error_VMerror); 175 for (y = 0; y < pdev->height; ++y) { 176 code = gdev_prn_get_bits(pdev, y, line, &row); 177 if (code < 0) 178 break; 179 fwrite((char *)row, raster, 1, file); 180 } 181 gdev_tiff_end_strip(&tfdev->tiff, file); 182 gdev_tiff_end_page(&tfdev->tiff, file); 183 gs_free_object(pdev->memory, line, "tiff24_print_page"); 184 } 185 186 return code; 187 } 188