126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross/* 226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * Copyright (C) 2012 The Android Open Source Project 326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * 426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 526a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * you may not use this file except in compliance with the License. 626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * You may obtain a copy of the License at 726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * 826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * http://www.apache.org/licenses/LICENSE-2.0 926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * 1026a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * Unless required by applicable law or agreed to in writing, software 1126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * distributed under the License is distributed on an "AS IS" BASIS, 1226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * See the License for the specific language governing permissions and 1426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross * limitations under the License. 1526a417f68526fee861bb527f1a4e3ed548979f93Colin Cross */ 1626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 1726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross#include <errno.h> 1826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross#include <setjmp.h> 1926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross#include <stdio.h> 2026a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 2126a417f68526fee861bb527f1a4e3ed548979f93Colin Crossextern "C" { 2226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross#include "jpeglib.h" 2326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross} 2426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 2526a417f68526fee861bb527f1a4e3ed548979f93Colin Crossstatic inline uint8_t from565to8(uint16_t p, int start, int bits) { 2626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross uint8_t c = (p >> start) & ((1 << bits) - 1); 2726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross return (c << (8 - bits)) | (c >> (bits - (8 - bits))); 2826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross} 2926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 3026a417f68526fee861bb527f1a4e3ed548979f93Colin Crossstruct sf_jpeg_error_mgr { 3126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross struct jpeg_error_mgr jerr; 3226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jmp_buf longjmp_buffer; 3326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross}; 3426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 3526a417f68526fee861bb527f1a4e3ed548979f93Colin Crossvoid sf_jpeg_error_exit(j_common_ptr cinfo) { 3626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross struct sf_jpeg_error_mgr *sf_err = (struct sf_jpeg_error_mgr *)cinfo->err; 3726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross longjmp(sf_err->longjmp_buffer, 0); 3826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross} 3926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 4026a417f68526fee861bb527f1a4e3ed548979f93Colin Crossint writeJpegFile(const char *filename, uint8_t *frame, int width, int height) { 4126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross struct sf_jpeg_error_mgr sf_err; 4226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross struct jpeg_compress_struct cinfo; 4326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross uint8_t row_data[width * 3]; 4426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross JSAMPROW row_pointer = row_data; 4526a417f68526fee861bb527f1a4e3ed548979f93Colin Cross FILE *f; 4626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 4726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross f = fopen(filename, "w"); 4826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross if (!f) { 4926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross return -errno; 5026a417f68526fee861bb527f1a4e3ed548979f93Colin Cross } 5126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 5226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross cinfo.err = jpeg_std_error(&sf_err.jerr); 5326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross sf_err.jerr.error_exit = sf_jpeg_error_exit; 5426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross if (setjmp(sf_err.longjmp_buffer)) { 5526a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_destroy_compress(&cinfo); 5626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross fclose(f); 5726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross return -1; 5826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross } 5926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 6026a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_create_compress(&cinfo); 6126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_stdio_dest(&cinfo, f); 6226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 6326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross cinfo.image_width = width; 6426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross cinfo.image_height = height; 6526a417f68526fee861bb527f1a4e3ed548979f93Colin Cross cinfo.input_components = 3; 6626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross cinfo.in_color_space = JCS_RGB; 6726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 6826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_set_defaults(&cinfo); 6926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_set_quality(&cinfo, 80, TRUE); 7026a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 7126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_start_compress(&cinfo, TRUE); 7226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 7326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross for (int row = 0; row < height; row++) { 7426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross uint16_t *src = (uint16_t *)(frame + row * width * 2); 7526a417f68526fee861bb527f1a4e3ed548979f93Colin Cross uint8_t *dst = row_data; 7626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross for (int col = 0; col < width; col++) { 7726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross dst[0] = from565to8(*src, 11, 5); 7826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross dst[1] = from565to8(*src, 5, 6); 7926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross dst[2] = from565to8(*src, 0, 5); 8026a417f68526fee861bb527f1a4e3ed548979f93Colin Cross dst += 3; 8126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross src++; 8226a417f68526fee861bb527f1a4e3ed548979f93Colin Cross } 8326a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_write_scanlines(&cinfo, &row_pointer, 1); 8426a417f68526fee861bb527f1a4e3ed548979f93Colin Cross } 8526a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 8626a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_finish_compress(&cinfo); 8726a417f68526fee861bb527f1a4e3ed548979f93Colin Cross jpeg_destroy_compress(&cinfo); 8826a417f68526fee861bb527f1a4e3ed548979f93Colin Cross 8926a417f68526fee861bb527f1a4e3ed548979f93Colin Cross fclose(f); 9026a417f68526fee861bb527f1a4e3ed548979f93Colin Cross return 0; 9126a417f68526fee861bb527f1a4e3ed548979f93Colin Cross} 92